定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类 2类图描述
3代码实现:class Product { protected: Product(); public: virtural ~Product() = 0; }; class ConcreteProduct: public Product {};
class Creator { protected: Creator(); public: //核心接口所在,该方法定义产品生成 virtual Product*FactoryMethod() = 0; virtual ~Creator() = 0; }; class ConcreteCreator:public Creator { public: Product * CreatProduct() { retun new ConcreteProduct(); } }; 4 问题在2中实现的工厂方法中,因为具体的工厂生产Product都是特定在Create函数中实现的。所以当ConcreteProduct 类型增多时,可能就需要决策具体实例化哪个Product了 那么, 解决方案可以是 ①给CreateProduct增加参数进行决策; Product *ConcreteCreator::CreatProduct(int index) { switch(index) { case 1: return ConcreteProduct1(); break; case 2: return ConcreteProduct2(); break; } } ②利用模板方法,由用户需求决定具体的实例化对象类型。 template<class T> Product *ConcreteCreator<T>::CreatProduct() { return T(); } 5工厂方法应用①优点: 良好封装,创建产品只需要知道类型就好,具体创建由工厂返回 扩展性强,当产品类型增多,代码整体结构并没有太大变化。“拥抱变化” 屏蔽产品类,调用者只需要知道产品接口就好 典型的解耦框架。高层只需要知道产品的抽象类,符合迪米特法则,依赖倒置原则,里氏替换原则 6 使用场景①他是new产品的一个替代品 ②需要灵活地,可扩展的框架是,考虑工厂模式 ③在异构项目中,可以通过工厂模式实现系统同构化,只需要关进具体的接口接合问题 ④在测试驱动开发的框架中。可以通过工厂方法将具体测试者所依赖的其他类虚拟出来,从而避免耦合
7扩展① 缩小为简单工厂模式 方案: 工厂模式:有不同的工厂车间继承自抽象工厂基类,为生产不同产品而运行。或者如上通过参数传递确定生产产品类型 简单工厂:只生产一种商品的工厂。 所以这时的工厂就应当是具体的某一个ConcreteFactory,而不用虚拟工厂存在
②升级为多个工厂类 描述: 以上所说由参数或者模板方法确定具体产品类型所指是一个可以生产多种相关产品的工厂了(不同车间生产) 那么要做到单一职责--一个工厂只生产一种特定产品,就应当将车间等级提升为工厂了。这就是多工厂了
实现变动: //两种产品
class ConcreteProduct1:public Product{}; class ConcreteCreator1:public Creator { public: Product ConcreteProduct1* CreatorProduct() { return new ConcreteProduct1(); } }; class ConcreteCreator2:public Creator { public: Product ConcreteProduct2* CreatorProduct() { return new ConcreteProduct2(); } };
③替换单例模式 描述:因为单例模式拥有,接口少,扩展性差的缺点,而我们的工厂模式又恰好拥有这个特点。那么将之接合,两全其美 实现: class Singleton { //保证工厂方法可以调用其构造函数进行初始化 friend class SingletonFactory; protected: Singleton(){} public: void doSomething() {//业务处理} }; class SingletonFactory { private: //包装单例的指针,外部所得永远为这一个指针。具体的单例确定:RAII(资源获取即初始化) static Singleton *_singleton; public: static Singleton* GetSingleton() { return _singleton; } }; Singleton * SingletonFactory::_singleton = new Singleton();
④延迟初始化/最大连接数问题 问题举例:在系统中,因为资源及CPU限制,往往会有数据库连接数量MAX限制。而连接的数据库类型又可能不一致type1,2,3........。 看到这个,我们可能会想到多例模式。但是这个问题又存在数据库类型不一致问题了。 于是就找到工厂方法了。
实现: class ProductFactory { private: static Map<string,product> prMap = new HashMap();//用于已经连接数据库的保存 public: static product NewConnection(string type) { Product pr = NULL; if(prMap.hasConnention(type)) { pr = prMap.get(type);
} else { //确定类型 switch(type) { case typePr pr = new (typePr); prMap.put(typePr); } } return pr; } }; 注:以上代码并非可运行的
补充: 工厂模式的伟大,可以和其他模式混合使用:单例,模板方法,原型模式等。 (责任编辑:好模板) |