您的位置:首页 > 其它

工厂模式:封装对象的创建(一、在基类中定义一个静态成员函数)

2015-12-07 10:59 549 查看
当我们发现需要添加新的类型到一个系统中时,最明智的首要步骤就是用多态机制为这些新类型创建一个共同的接口。

用这种方法可以将系统中多余的代码与新添加的特定类型的代码分开。新类型的添加并不会搅乱已存在的代码...或者至少看上去如此。

起初它似乎只需要在继承新类的地方修改代码,但这并非完全正确,仍须创建对象,在创建对象的地方必须指定要使用的准确的构造函数。

因此,如果创建对象的代码遍布整个应用的程序,在增加新类型时将会遇到同样的问题---------仍然必须找出代码中所有与新类型相关的地方。

这是由类的创建而不是类型的使用(类型的使用问题已经被多态机制解决了)而引起的。

解决该问题的方法就是强制用一个通用的工厂(factory)来创建对象,而不允许将创建对象的代码散布整个系统。

如果程序中所有的需要创建对象的代码都转到这个工厂(factory)执行,那么在新增加对象时所要做的全部工作就是只需要修改工厂。

这种设计就是工厂方法(Factory Method)模式的一种变体。

举个例子:(实现工厂模式的一种方法就是在基类中定义一个静态成员函数)

#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 BadShapeCreation : public logic_error 
    {   
    public:
    BadShapeCreation(string type): logic_error("Cannot create type " + type) {}
    };  

    static Shape* factory(const string& type)
    throw(BadShapeCreation);
};

class Circle : public Shape 
{
    Circle() {} // Private constructor
    friend class Shape;
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 Shape;
public:
    void draw()
    {
        cout << "Square::draw" << endl;
    }
    void erase()
    {
        cout << "Square::erase" << endl;
    }
    ~Square()
    {
        cout << "Square::~Square" << endl;
    }
};
Shape* Shape::factory(const string& type)
throw(Shape::BadShapeCreation) 
{
    if(type == "Circle") return new Circle;
    if(type == "Square") return new Square;
    throw BadShapeCreation(type);
}

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(Shape::factory(sl[i]));
    } catch(Shape::BadShapeCreation e)
    {
        cout << e.what() << endl;
        purge(shapes);
        return -1;
    }
    for(size_t i = 0; i < shapes.size(); i++)
    {
        shapes[i]->draw();
        shapes[i]->erase();
    }
    purge(shapes);
}



函数factory ()允许以一个参数来决定创建何种类型的Shape  在这里,参数类型为string  也可以是任何数据集 。

在添加新的Shape类型时,函数factory()是当前系统中唯一需要修改的代码。

(对象的初始化数据大概也可以由系统外获得。而不必像本例中来自硬编码数组。)

为了确保对象的创建只能发生在函数factory()中,

Shape的特定类型的构造函数被设为私有的,同时Shape被声明为友元类,因此factory()能够访问这些构造函数。

(也可以只将Shape::factory() 声明为友元函数,但是似乎声明整个基类为友元类也没什么大碍。)

这样的设计还有另外一个重要的含义——基类Shape现在必须了解每个派生类的细节——这是面向对象设计试图避免的一个性质,

对于结构框架或者任何类库来说都应该支持扩充,但是这样一来,系统很快就会变得笨拙,因为一旦新类型被加入到这种层次结构中,

基础类就必须更新,可以使用多态工厂(polymorphic    factory)来避免这种循环依赖。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  工厂模式 对象