工厂模式有三种,分别是:简单工厂模式,工厂模式,抽象工厂模式
要理解为什么要用工厂模式,首先我们要这样编程:例如一家游戏公司已经写好了 飞机类文件,坦克类文件,潜艇类文件,并把他们封装好让程序员们来调用(姑且把封装好的文件叫库文件),而程序员调用来写程序,姑且把程序员叫做使用者。好,理解这句话我们就继续往下说。
无论哪种工厂模式,都不会给你直接 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*/