您的位置:首页 > 其它

工厂模式:封装对象的创建(二、多态工厂)

2015-12-07 15:28 495 查看
在上篇中,静态成员函数  static Shape* factory(const string& type) 迫使所有创建对象的操作都集中在一个地方,因此这个地方就是唯一需要修改代码的地方。这是一个合理的决解方法,因为它完美的封装了对象的创建过程。但是工厂方法模式——可以使不同类型的的工厂派生自基本类型的工厂。工厂方法事实上就是多态工厂模式的一个特例。所以下面例子是——工厂方法模式做为一个单独的类中的虚函数出现。#include <stdexcept>#include <cstddef>#include <string>#include <vector>#include <algorithm>#include <iostream>using namespace std;template<class Seq> void purge(Seq& c){typename Seq::iterator i;for(i = c.begin(); i != c.end(); ++i){delete *i;*i = 0;}}// Iterator version:template<class InpIt> void purge(InpIt begin, InpIt end){while(begin != end){delete *begin;*begin = 0;++begin;}}class Shape{public:    virtual void draw() = 0;    virtual void erase() = 0;    virtual ~Shape() {}};class ShapeFactory {    virtual Shape* create() = 0;    static map< string , ShapeFactory* > factories;public:    virtual ~ShapeFactory(){}    friend class ShapeFactoryInitializer;    class BadShapeCreation : public logic_error    {       public:        BadShapeCreation(string type): logic_error("Cannot create type " + type) {}    };      static Shape * createShape(const string& id) throw(BadShapeCreation)    {           if(factories.find(id) != factories.end())            return factories[id]->create();        else            throw BadShapeCreation(id);    }   };
//define static object
map< string , ShapeFactory* > ShapeFactory::factories;

class Circle : public Shape 
{
    Circle() {} // Private constructor
    friend class ShapeFactoryInitializer;
    class Factory;
    friend class Factory;
    class Factory:public ShapeFactory
    {
        public:
            Shape* create()
            {
                return new Circle;
            }
            friend class ShapeFactoryInitializer;
    };
public:
    void draw()
    {
        cout << "Circle::draw" << endl;
    }
    void erase()
    {
        cout << "Circle::erase" << endl;
    }

    ~Circle()
    {
        cout << "Circle::~Circle" << endl;
    }
};
class Square : public Shape 
{
    Square() {}
    friend class ShapeFactoryInitializer;
    class Factory;
    friend class Factory;
    class Factory:public ShapeFactory
    {
        public:
            Shape* create()
            {
                return new Square;
            }
            friend class ShapeFactoryInitializer;
    };
public:
    void draw()
    {
        cout << "Square::draw" << endl;
    }
    void erase()
    {
        cout << "Square::erase" << endl;
    }
    ~Square()
    {
        cout << "Square::~Square" << endl;
    }
};

//Singleton to initialize the ShapeFactory
class ShapeFactoryInitializer
{
    static ShapeFactoryInitializer si;
    ShapeFactoryInitializer()
    {
        ShapeFactory::factories["Circle"]=new Circle::Factory;
        ShapeFactory::factories["Square"]=new Square::Factory;
    }
    ~ShapeFactoryInitializer()
    {
        map<string,ShapeFactory*>::iterator it=ShapeFactory::factories.begin();
        while(it!=ShapeFactory::factories.end())
            delete it++->second;
    }
};
//static member definition
ShapeFactoryInitializer ShapeFactoryInitializer::si;

char* sl[] = { "Circle", "Square", "Square","Circle", "Circle", "Circle", "Square"};

int main()
{

    vector<Shape*> shapes;
    try {
        for(size_t i = 0; i < sizeof sl / sizeof sl[0]; i++)
            shapes.push_back(ShapeFactory::createShape(sl[i]));
    } catch(ShapeFactory::BadShapeCreation e)
    {
        cout << e.what() << endl;

        return -1;
    }
    for(size_t i = 0; i < shapes.size(); i++)
    {
        shapes[i]->draw();
        shapes[i]->erase();
    }
    purge(shapes);
}
工厂方法模式作为virtual create() 出现在它自己的 ShapeFactory 类中,这是一个私有的成员函数。意味着不能直接调用它,但是可以被覆盖。Shape 的子类必须创建各自的 ShapeFactory子类,并且覆盖成员函数 create()以创建其自身类型的对象。这些工厂是私有的,只能被工厂方法模式访问。采用这种方法的所有客户代码都必须通过工厂方法模式创建对象。Shape对象的实际创建是通过调用ShapeFactory::createShape() 完成对的,这是一个静态成员函数,使用ShapeFactory 中的map 根据传递给它的标识符找到相应的工厂对象。工厂直接创建Shape 对象,但是可以设想一个更为复杂的问题:在某个地方返回一个合适的工厂对象。然后该工厂对象被调用者用于以更复杂的方法创建一个对象。然而,似乎在大多数情况下不需要这么复杂地使用多态工厂方法模式。注意,ShapeFactory 必须通过装载它的map 与工厂对象进行初始化,这些操作发生在单例ShapeFactoryInitializer, 以便将工厂的一个实例插入到map中。这些额外的复杂的操作再次暗示,如果不需要创建独立的工厂对象,应该尽可能使用静态(static)工厂方法模式
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  工厂模式 多态