首页 > 代码库 > 设计模式实现C++ --工厂模式
设计模式实现C++ --工厂模式
定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
类型:创建型模式
分类:
简单工厂模式,它的主要特点是需要在工厂类中做判断,从而创造相应的产品。当增加新的产品时,就需要修改工厂类。有点抽象,举个例子就明白了。有一家生产处理器核的厂家,它只有一个工厂,能够生产两种类型的产品。客户需要什么样的产品,一定要显示地告诉生产工厂。下面给出一种实现方案:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 class product 6 { 7 public: 8 virtual void show(){} 9 };10 11 class productA:public product12 {13 public:14 virtual void show()15 {16 cout << "product A" << endl;17 }18 };19 20 class productB:public product21 {22 public:23 virtual void show()24 {25 cout << "product B" << endl;26 }27 };28 29 class Factory30 {31 public:32 static product* CreateProduct(string pro)33 {34 if(pro == "A")35 return new productA();36 else if(pro == "B")37 return new productB();38 return NULL;39 }40 }
这样设计的主要缺点之前也提到过,就是要增加新的核类型时,就需要修改工厂类。这就违反了开放封闭原则:软件实体(类、模块、函数)可以扩展,但是不可修改。于是,工厂方法模式出现了。
工厂方法模式,是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。举个例子,有两个工厂,工厂A只生产PROUCUTA, 工厂B只生产PRODUCTB,现在客户需要做的就是找到对应的工厂,而不需要告诉工厂我需要做什么型号的产品,实现方案如下:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 class product 6 { 7 public: 8 virtual void show(){} 9 };10 11 class productA:public product12 {13 public:14 virtual void show()15 {16 cout << "product A" << endl;17 }18 };19 20 class productB:public product21 {22 public:23 virtual void show()24 {25 cout << "product B" << endl;26 }27 };28 29 class Factory30 {31 public:32 virtual product* CreateProduct() = 0;33 };34 35 class FactoryA:public Factory36 {37 public:38 product* CreateProduct() { return new productA();}39 };40 41 class FactoryB:public Factory42 {43 public:44 product* CreateProduct() {return new productB();}45 };46 47
工厂方法模式的缺点就是每增加一种产品,就要增加一个工厂, 如果这个公司迅速发展,新增了很多产品,那么就要开设很多相应的工厂。在C++实现中,就是要定义一个个的工厂类。显然,相比简单工厂模式,工厂方法模式需要更多的类定义。
抽象工厂模式, 它的定义为提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的的类,具体应用,有两个农场,一个家场专门生产北方水果和蔬菜,一个农声只生产热带水果和蔬菜,下面给出实现的代码。
1 #include <iostream> 2 using namespace std; 3 4 class Fruit 5 { 6 public: 7 virtual void show() = 0; 8 }; 9 10 class Veggie11 {12 public:13 virtual void show() = 0;14 };15 16 class NorthernFruit:public Fruit17 {18 public:19 void show()20 {21 cout << "NortherFruit" << endl;22 }23 };24 25 class TropicalFruit:public Fruit26 {27 public:28 void show()29 {30 cout << "TropicalFruit" << endl;31 }32 };33 34 class NorthernVeggie:public Veggie35 {36 public:37 void show()38 {39 }40 };41 42 class Gardener43 {44 public:45 virtual Fruit* createFruit() = 0;46 virtual Veggie* createVeggie() = 0;47 };48 49 class NorthernGardener:public Gardener50 {51 public:52 Fruit* createFruit()53 {54 return new NorthernFruit();55 }56 57 Veggie* createVeggie()58 {59 return new NorthernVeggie();60 }61 };62 63 64 class TropicalGardener:public Gardener65 {66 public:67 Fruit* createFruit()68 {69 return new TropicalFruit();70 } Veggie* createVeggie()71 {72 return new TropicalVeggie();73 }74 };75 76 77
优点:
- 可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
- 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
- 降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。
适用场景:
不管是简单工厂模式,工厂方法模式还是抽象工厂模式,他们具有类似的特性,所以他们的适用场景也是类似的。
首先,作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
其次,工厂模式是一种典型的解耦模式,迪米特法则在工厂模式中表现的尤为明显。假如调用者自己组装产品需要增加依赖关系时,可以考虑使用工厂模式。将会大大降低对象之间的耦合度。
再次,由于工厂模式是依靠抽象架构的,它把实例化产品的任务交由实现类完成,扩展性比较好。也就是说,当需要系统有比较好的扩展性时,可以考虑工厂模式,不同的产品用不同的实现工厂来组装。