有多个工厂模式是为了满足不同的需求,接下来我们从需求角度出发来了解每种工厂模式。
我们以为枪械厂和弹药厂为例。玩过《绝地求生》应该都知道,每种枪支的子弹都有其特定规格,不同枪支子弹规格不一样,子弹是无法通用的。比如:
枪支 | 子弹规格(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();
}
总结
这几个工厂模式,其实就是满足了生产不同复杂度的对象。
- 简单工厂模式:生产固定几个类的对象。
- 工厂方法模式:这个一个基类所有派生类的对象。
- 抽象工厂模式:一次创建一组对象。