有多个工厂模式是为了满足不同的需求,接下来我们从需求角度出发来了解每种工厂模式。
我们以为枪械厂和弹药厂为例。玩过《绝地求生》应该都知道,每种枪支的子弹都有其特定规格,不同枪支子弹规格不一样,子弹是无法通用的。比如:
| 枪支 | 子弹规格(mm) |
|---|---|
| M4A1 | 5.56 |
| AK47 | 7.62 |
| Kar98K | 7.62 |
| UZI | 9.00 |
我们可能有如下生产需求:
点击查看【processon】
- 产品系列
- 枪支系列
- M4A1、AK47、98K、UZI等种类。
- 弹药系列
- 5.56、7.62、9.00等种类。
- 枪支系列
- 工厂:以生产线划分。
从代码上来说就是,工厂需要负责创建固定几个类的对象,这几个类有相同(间接)基类。
既然情况这么简单,我们也就不需要去区分什么生产线、什么产品系列了,就那么几个产品,搞这么麻烦干嘛。就一个工厂,直接生产就行了。
UML
代码设计
enum GunType {GunType_AK47,GunType_M4A1,};struct Gun{virtual Gun* justShow() = 0; //没子弹,只能用来show}struct M4A1 : Gun { //AK47类似。void Gun* justShow(){ return this; }};struct GunFactory {Gun* produce(GunType t) {switch (t) {case M4A1: return new M4A1();case AK47: return new AK47();default: return NULL;}}};int main() {GunFactory factory;factory.produce(GunType_AK47)->justShow(); //仅做示范,忽略动态内存泄露的问题factory.produce(GunType_M4A1)->justShow(); //仅做示范,忽略动态内存泄露的问题}
工厂方法模式:Factory method
一般情况的需求都比简单工厂复杂,因此简单工厂模式也不列入我们的工厂模式中了。
更一般的需求是:工厂需要负责所有类型枪支的生产包括未来的新型枪支。
从代码上来说就是,工厂需要负责创建某一个基类所有派生类对象。
如果按照简单工厂模式,虽然可以满足需求,但是很勉强,第一,因为需要创建的对象类型可能很多,工厂会很臃肿,第二,如果出现新类型,就需要改动工厂,这不是明智的选择。
这时候就需要工厂方法模式了。
UML
代码设计
struct Gun {virtual Gun* justShow() = 0;};struct AK47 : Gun{Gun* justShow(){ return this; } //还是没有子弹,只能show了。};struct GunFactory { //专门负责造枪支virtual Product *produce() = 0;};struct FactoryAK47 : GunFactory { //FactoryM4A1类似。Gun *produce(){return new AK47();}};int main() {GunFactory *factoryAK47 = new FactoryAK47() , *factoryM4A1 = new FactoryM4A1();factoryAK47->produce(); //多态factoryM4A1->produce(); //多态}
抽象工厂模式:Abstract factory
可能还会有比工厂方法更复杂一点的需求,比如:
工厂需要同时负责生产枪支和它对应的弹药,有同学可能会想,为啥不分开工厂生产?我们应该从需求出发,这样的需求是合理,所以我们就应该要满足。
从代码上说就是,工厂的每次创建,需要创建一组不同“系列”的对象,这些对象之间有很紧密的关系。
UML
代码设计
struct Gun {virtual Gun* load(Bullet*) = 0;virtual Gun* fire() = 0;};struct Bullet {virtual void shoot() = 0;};struct AK47 : Gun { //M4A1类似。Gun* fire(Bullet*){ //逻辑就不写了,必须要上556的子弹。return this;}Gun* fire(){return this}};struct Bullet762 : Bullet { //Bullet556类似。void shoot() { }};struct WeaponFactory { //枪支弹药制造商virtual Gun* produceGun() = 0;virtual Bullet* produceBullet() = 0;};struct FactoryAK47 : WeaponFactory { //FactoryM4A1类似Gun* produceGun(){return new AK47();}Bullet* produceBullet(){return new Bullet762();}};int main() {GunFactory *factoryAK = new FactoryAK(), *factoryM4A1 = new FactoryM4A1();Gun* pGun47 = factoryAK.produceGun();Bullet* pBulletAK = factoryAK.produceBullet();Gun* pM4A1 = FactoryM4A1.produceGun();Bullet* pBulletM4A1 = FactoryM4A1.produceBullet();//多态:相同静态类型的Gun、Bullet,fire出来却不一样。pGun47->load(pBulletAK)->fire();pM4A1->load(pBulletM4A1)->fire();}
总结
这几个工厂模式,其实就是满足了生产不同复杂度的对象。
- 简单工厂模式:生产固定几个类的对象。
- 工厂方法模式:这个一个基类所有派生类的对象。
- 抽象工厂模式:一次创建一组对象。
