C++三种工厂模式介绍及其区别

来源:互联网 发布:带着淘宝穿古代txt书包 编辑:程序博客网 时间:2024/05/17 09:22

工厂模式有三种,分别是:简单工厂模式工厂模式抽象工厂模式


要理解为什么要用工厂模式,首先我们要这样编程:例如一家游戏公司已经写好了 飞机类文件,坦克类文件,潜艇类文件,并把他们封装好让程序员们来调用(姑且把封装好的文件叫库文件),而程序员调用来写程序,姑且把程序员叫做使用者。好,理解这句话我们就继续往下说。

无论哪种工厂模式,都不会给你直接 new 具体的产品对象的。使用者能做的只是操作两个接口--->抽象产品对象和抽象工厂对象。那这里又怎么理解呢?

以战争游戏为例,使用工厂模式的话,调用者(一般调用库文件写main的程序员)不能直接 new(创建) 出坦克对象或者飞机对象,他能new的只是一个武器对象(抽象产品类),然后通过对武器对象(抽象产品类)操作,来获得一个具体的武器对象,如坦克对象,如飞机对象,这里用的操作方法就是多态了,所以工厂模式处处都有多态。

而抽象工厂也是同样理解,工厂生成产品,所以这里我们可以把抽象工厂类看成一个武器车间对象,根据使用者(程序员)的操作,可以通过多态把武器车间设置成坦克车间对象,飞机车间对象。而记住,程序员是不可以直接 new出坦克车间的,这是工厂模式设计出来所避免的东西。


看到这里,相信大家会有疑问,为什么就不允许直接 new 出坦克对象,飞机对象等具体的对象呢?

因为试想一下,一个战争游戏,只有一个车间,步兵从那里出,坦克从那里出,飞机从那里出,造成的后果就是大量的代码混杂在一起,增加维护难度。

而且设计模式有一个原则就是面向接口编程,倾向于把一切封装起来,只露出接口,这样的好处是代码管理,维护方便。



下面介绍简单工厂模式:简单工厂模式一般比较少用,因为本身有较大缺点。其优点就是不用记那么多类名,只要传入对应表示参数就能创建对应类了,

例如1表示坦克,就参数type=1,2等于飞机,就type=2,等待再讲缺点在哪


简单工厂模式:

简单工厂一般向工厂对象传入参数type来决定生产哪种产品。


#include<iostream>using namespace std;/*以战争游戏为例*/ class AbstractProduct  //抽象武器类 {public:virtual void operation()=0; } ;class AbstractFactory//抽象车间 {public:virtual AbstractProduct *createproduct(int type)=0;};class ProductA:public AbstractProduct//坦克类 {public:void operation(){cout<<"this is ProductA"<<endl;}};class ProductB:public AbstractProduct//飞机类 {public:void operation(){cout<<"this is productB"<<endl;}};/*大武器车间,其实这里不用抽象工厂也行,直接用SimpleFactory类也可以但是设计模式都要抽象,所以按规矩就写一下抽象工程类。*/ class SimpleFactory:public AbstractFactory{public:AbstractProduct *createproduct(int type){if(type == 1)return new ProductA();if(type == 2)return new ProductB();}};int main(){AbstractProduct *p = NULL;AbstractFactory *f = NULL;f = new SimpleFactory();p = f->createproduct(1);//当type=1时,创建产品A对象,type=2,创建产品B p->operation();return 0;}

为什么说简单工厂模式一般不用,因为它违反了设计模式的 开闭原则。

什么叫开闭原则呢?

就是对代码模块,允许扩展,就是增加代码量,但现在的代码不允许修改。


想想简单工厂模式,如果我要增加导弹类武器,怎么办?只能修改SimpleFactory类中的代码,增加 if(type=3),就new一个导弹类。

这本质上修改了SimpleFactory代码模块。下面要讲的第二种工厂模式---工厂模式就可以解决这个问题。



工厂模式:


#include<iostream>using namespace std;class AbstractWeapon//抽象武器类 {public:virtual void operation()=0;};class J10:public AbstractWeapon//J10战斗机 {public:void operation(){cout<<"this is J10"<<endl;}};class F22:public AbstractWeapon//F22战斗机 {public:void operation(){cout<<"this is F22"<<endl;}};class Tank1:public AbstractWeapon//一号坦克 {public:void operation(){cout<<"this is T1"<<endl;}};///////////////////////////////////////////////////////////class AbstractFactory//抽象工厂 {public:virtual AbstractWeapon *create1()=0;virtual AbstractWeapon *create2()=0;};class PlaneFactory:public AbstractFactory//飞机工厂 {public:AbstractWeapon *create1(){return new J10();}AbstractWeapon *create2(){return new F22();}};class TankFactory:public AbstractFactory//坦克工厂 {public:AbstractWeapon *create1(){return new Tank1();}AbstractWeapon *create2(){}};int main(){AbstractWeapon *p=NULL;AbstractFactory *f = NULL;f = new TankFactory();//选择坦克工厂 //f = new PlaneFactory;    //选择飞机工厂 p = f->create1();p->operation();return 0;}/*打印结果:This is T1*/ 

由上面代码可知,通过增加多态的代码,可以扩展多一种工厂来生产新一类产品,从而不需要改动原来的代码模块,因为当你的代码量多的话,轻易改代码模块是很高风险的。上面的抽象工厂类相当于所有具体工厂的规格要求,如上,我在抽象工厂定义了2个纯虚函数用于创建对象,就是说,所有的具体工厂最多只能创建2种不同的武器,如(J10,F22),当然一种也可以,如坦克类就只有一号坦克。你想创建多种不同的武器,往抽象类中加纯虚函数即可


但这种工厂模式也是有缺陷的,就是一种工厂只能生产一类产品,如飞机工厂,只能生成各种飞机。

相信大家都玩过红色境界,例如现在有中美两个国家,中国有自己的飞机坦克,美国也有自己的飞机坦克,那我们实现的时候,绝不能在美国工厂能生成中国工厂的东西。

而抽象工厂模式能有一个更好的分类功能



抽象工厂模式:

抽象工厂可以使一类工厂生产不同类的的产品,但这些产品都有一定的联系。


#include<iostream>using namespace std;class AbstractPlane//抽象飞机类 {public:virtual void operation()=0;};class J10:public AbstractPlane//中国J10战斗机 {public:void operation(){cout<<"this is J10"<<endl;}};class F22:public AbstractPlane//美国F22战斗机 {public:void operation(){cout<<"this is F22"<<endl;}};//////////////////////////////////////////class AbstractTank//抽象坦克类 {public:virtual void operation()=0;};class China_Tank:public AbstractTank//中国坦克 {public:void operation(){cout<<"this is china tank"<<endl;}};class USA_Tank:public AbstractTank//美国坦克 {public:void operation(){cout<<"this is USA Tank"<<endl;}};/////////////////////////////////////class AbstractFactory//抽象工厂类 {public:virtual AbstractPlane *CreatePlane()=0;virtual AbstractTank *CreateTank()=0;};class China_Factory:public AbstractFactory//中国工厂 {public:AbstractPlane *CreatePlane(){return new J10();}AbstractTank *CreateTank(){return new China_Tank();}};class USA_Factory:public AbstractFactory//美国工厂 {public:AbstractPlane *CreatePlane(){return new F22();}AbstractTank *CreateTank(){return new USA_Tank();}};///////////////////////////////////////int main(){AbstractPlane *plane = NULL;AbstractTank *tank = NULL;AbstractFactory *factory = NULL;factory = new China_Factory();//生成中国工厂 plane = factory->CreatePlane();//生成中国的飞机 plane->operation();//调用中国飞机的方法 return 0;}/*打印结果:This is J10*/ 





























0 0