设计模式:工厂模式

来源:互联网 发布:体育网络电视 编辑:程序博客网 时间:2024/06/05 21:09

工厂模式的意图是将生成对象的代码集中到一个地方,以方便统一管理,最简单的工厂模式是由基类负责生成各种派生类的对象,举个简单例子如下:

class Base {public:static Base* create(const string &str);};class A : public Base {};class B : public Base {};Base* Base::create(const string &str) {if(str == "A") return new A();if(str == "B") return new B();return NULL;}

这样就可以通过Base::create来创建A或B的对象,注意到create定义成Base的静态函数即可,但是就上面的例子而言,我们依然可以绕过Base::create而创建A或B的对象,即通过A、B的默认构造函数,所以更加严谨的做法可能是将A、B的默认构造函数(拷贝构造函数)定义为private,如下:

class Base {public:static Base* create(const string &str);};class A : public Base {A() {}A(const A&) {}friend Base* Base::create(const string&);};class B : public Base {B() {}B(const B&) {}friend Base* Base::create(const string&);};Base* Base::create(const string &str) {if(str == "A") return new A();if(str == "B") return new B();return NULL;}

注意到A、B的默认构造函数(及拷贝构造函数)被设置成了private,这是为了避免用户通过A、B的构造函数直接生成各自的对象,换言之,强迫用户将生成A、B对象的任务交给Base::create,同时,为了在Base::create中调用A、B的构造函数,需要将Base::create设置为A、B的友元。在实际的使用中,如果我们想增加另外一个派生于Base的类型C,那么只需修改Base::create中的代码即可。

在上面这种最简单的工厂模式中,基类和派生类的耦合还是比较紧的,因为基类的create需要直接操作派生类的构造函数,事实上,我们可以避免基类直接操作派生类的构造函数,这就是所谓的多态工厂。在多态工厂的设计模式中,派生类A和B都有各自的专属工厂,这个专属工厂直接操作A或B的构造函数,基类有个大工厂,这个大工厂通过调用各派生类的专属工厂来生成各派生类的对象,看个简单例子:

class Base {};class BaseFactory {static BaseFactory bf;static map<string, BaseFactory*> factories;protected:BaseFactory(){}BaseFactory(int);public:virtual Base* create(){ return NULL; }static Base* createProduct(const string &str);};

这是基类以及基类工厂,我们重点关注基类工厂:BaseFactory,这个工厂有一个map结构的数据成员:factories,factories用于保存各派生类的专属工厂,同时,基类工厂还有一个成员函数:createProduct,用于创建各派生类的对象,createProduct的定义如下:

Base* BaseFactory::createProduct(const string &str) {if(factories.find(str) != factories.end())return factories[str]->create();}
所以在createProduct中通过使用actories中保存的各专属工厂来创建派生类对象,str可以是派生类的名字,用于标识创建哪个派生类的对象。再回到BaseFactory中,还有一个成员函数create,这个函数将来会被派生类工厂重新定义,用以创建各派生类的对象,派生类及派生类工厂的定义如下:

class A : public Base {A() {}A(const A&) {}friend class BaseFactory;class Factory;friend class Factory;class Factory : public BaseFactory {public:Base* create() { return new A(); }};};
派生类工厂是作为派生类的嵌套类进行定义的,且访问属性为private,所以派生类工厂不能在派生类以外被使用,但是由于BaseFactory被定义成了派生类的友元,所以派生类工厂可以被BaseFactory访问,派生类工厂继承于BaseFactory,唯一要做的就是重新定义create(),在create()将完成派生类对象的创建。由于create为虚函数,所以即使使用BaseFactory类型的指针也可以正确访问派生类工厂的create(只要该指针真正指向的是派生类工厂对象)。完整的代码如下:

#include<iostream>#include<string>#include<map>using namespace std;class Base {};class BaseFactory {static BaseFactory bf;static map<string, BaseFactory*> factories;protected:BaseFactory(){}BaseFactory(int);public:virtual Base* create()  { return NULL; } static Base* createProduct(const string &str);};map<string, BaseFactory*> BaseFactory::factories;BaseFactory BaseFactory::bf(1);Base* BaseFactory::createProduct(const string &str) {if(factories.find(str) != factories.end())return factories[str]->create();}class A : public Base {A() {}A(const A&) {}friend class BaseFactory;class Factory;friend class Factory;class Factory : public BaseFactory {public:Base* create() { return new A(); }};};class B : public Base {B() {}B(const B&) {}friend class BaseFactory;class Factory;friend class Factory;class Factory : public BaseFactory {public:Base* create() { return new B(); }};};BaseFactory::BaseFactory(int) {BaseFactory::factories["A"] = new A::Factory;BaseFactory::factories["B"] = new B::Factory;}int main() { Base *p = BaseFactory::createProduct("A");return 0; }
对上面的代码再做几点解释:

1、基类工厂BaseFactory中有一个自身的static数据成员: bf ,因为bf的定义将发生在main()之前,所以bf存在的意义是调用构造函数以初始化factories,这里bf调用了有参的构造函数;

2、基类工厂BaseFactory中有两个构造函数,一个是无参的默认构造函数,另一个是有int参数的构造函数,前者是用于被派生类工厂调用的(因为创建派生类工厂对象的时候需要调用其基类的默认构造函数),而后者只是为了在定义bf 的时使用,用于初始化factories;

上面的代码只是阐述了多态工厂的基本思想,仍然有很多可以改进的地方微笑,希望大家多提意见,总之,多态工厂就是使用派生类自己的工厂来创建派生类,所以基类就不需要了解太多派生类的细节,只要派生类向基类工厂注册了自己的专属工厂就行。






1 0
原创粉丝点击