简单工厂、工厂、抽象工厂模式
生活中当你想要买车子的时候,会去汽车销售店。而当你进去的时候,就会有销售人员给你介绍各种各样的车子,它的类型、品牌、价格等等。你想买那种的时候,只需要说一声,相关人员就会帮你办理相应手续,你就可以付款提车走人。
我这里也有个汽车销售店,只卖宝马、奔驰和大众。
- 起步阶段--简单工厂
刚开业的时候,没钱、没客户,因此我只请了一个销售员进行销售产品,因为节省资源,实现利益最大化。
而这个时候的交易流程:
销售员介绍->客户选择车子->交易结款。交易流程中,用户只需要知道我要买什么车子,而不会太过于车子是怎么来的,毕竟我的各种证件齐全。
而这种模式就叫做“简单工厂模式”,所有的产品都由一个销售员(工厂)负责出售或者被制造等等,而用户只需要向销售员提供足够的信息,“我要买大众”等等,就可以从销售员得到需要的车子(产品)。
而“简单工厂模式”是最简单的工厂模式,也是最基本的工厂模式,后面的工厂模式和抽象工厂模式,都是慢慢拓展来的。
对上述的交易流程通过uml进行描述 :
其中的Enum(ECarType)就是类似于销售员的讲解和一些产品说明书,你在其中选择,然后告诉给销售员(CCarFactory)所需要的产品,而销售员(CCarFactory)通过内部的一系列手续或者操作来得到结果,将你需要的产品(CCar)给你。而销售员(CCarFactory)内部就存在“业务逻辑”,就是他需要分析你的需求,然后使用不同车子对应的手续办理方法,而“简单工厂模式”就是将“业务逻辑”和“产品”从用户进行分离,解耦合。
可是随着时间的流逝,我的销售点扩张了,变大了,虽然汽车种类没有变化,但是各种型号变多了。这个时候销售不干了,她说:“这么多汽车型号和逐渐增多的客户流,我一个人哪里照顾的来。”
这就是“简单工厂”的不足之处:
- 型号、种类(产品)进行增加的时候,销售员(CCarFactory)必须修改内部逻辑,这就违反了“开发-封闭”原则,这可是最基本的原则
- 客户量的增加,反映出资源的浪费。如果销售员(CCarFactory)他真的记住了所有产品特点,但是他给用户讲的可能只是一种品牌的车子相关知识,其他的不浪费了吗?
因此产生了“工厂模式”,对“销售员(CCarFactory)”进行加工处理,让其遵循“开发-封闭”原则,也要保证对资源的充分利用。
(2)拓张阶段-工厂模式
我对销售员(CCarFactory)进行了拓张,一开始的销售员升职了,好吧,忘记介绍她叫“小A”,她现在的工作不是每天讲的口干舌燥的,然后还需要看客户脸色了,她成了经理,干着轻松的活,拿着更多的工资和分红。
这次我招了三个人,小B(负责奔驰相关的产品)、小C(负责大众相关的产品)、小D(负责宝马相关的产品)。而这个时候就不仅仅是人讲了,我还有一个大屏幕啦,然后一直循环展示一些产品,并且还附带有相关产品的销售员相片。
而这个时候的交易流程:
用户自己看大屏或者产品书->根据附带的相片找到想要的销售人员->在销售员(CCarFactory)的介绍下选择产品->交易结款。这个时候的流程图:
虽然流程图一样,但是根据具体讲解就知道,有些功能被用户承但了:
用户除了“说出选择”之外,还承但了“做出选择销售员(Factory)”的责任。因为我的客户多,但是我的销售员(Factory)少啊,所以只能是客户去选择销售员(Factory)了。而不是销售员(Factory)主动过来寻找客户,很傲娇的,而且现在大多数人也不太喜欢太过于热情的服务。那么我没就可以从销售员(Factory)中将“业务逻辑”这部分消除掉了,因为这部分的分析被用户通过“做出选择销售员(Factory)”已经完成了。
而这种销售流程就行“工厂模式”,用户自己进行销售员(Factory)选择,然后得到对应的销售员(Factory)的对象,然后进行车子(产品)的购买,而销售员(Factory)只需要知道自己所负责的一种品牌的车子的手续怎么办理就行了,然后办理手续,把车子交给用户。用uml显示:
其中ICarFactory接口就相当于你刚进商店的时候,一个虚拟的销售员(Factory)对象,然后你查看大屏或者产品说明,来选择(创建)对应的销售员(Factory)对象,而实际的这个销售员(Factory)可能是小B(CBenChiCarFactory)、小C(CDaZhongCarFactory)或小D(CBMWCarFactory),
然后他们给你将对应的产品和办理对应的手续,然后交易就完成了。而这个时候拓展就不需要改变“业务逻辑”了,只需要添加对应的接口和对应的销售员(Factory)对象就行了,而且每次只是让对应品牌的销售员负责对应的产品,也减少了资源浪费。
而随着卖出去的车子越来越多,相应的车损耗率也上升了,修改车灯、换个车玻璃等等的,我又嗅到了商机......
(3)形成产品家族--抽象工厂模式
我拓展了维修服务,我针对三种品牌的车子,拓展了对应车子的车玻璃商品,又是一波收入。但是我不想再花钱去请销售员了,太麻烦,又太费钱。我让小B负责奔驰相关的车玻璃产品、小C负责大众的、小D负责宝马的,最大多加点工资,嘿嘿。
而这个时候的交易流发生了简单的变化:
用户自己看大屏或者产品书->根据附带的相片找到想要的销售人员->在销售员(CCarFactory)的介绍下选择产品(选择买车子、还是买车玻璃并维修)->交易结款。只是用户找到对应的销售员后,所可以选择的服务增加了一项服务,流程图却没有变化。也就意味着代码修改不大,只是用户阶段多做一些选择就行了。因此,可以推出“抽象工厂模式”其本质就是“工厂模式”,“工厂模式”是对一种产品的模式,比如车子、房子等等,而“抽象工厂模式”则是再一种上增加了垂直的一类,比如车子和车子的车玻璃等等,大众说法就是“产品族”。
其UML表示为:
而且其拓展步骤不难,大体分为4步:
- 添加一个车子相关的产品,如车玻璃CMirror。
- 对CMirror进行派生,产生和车子种类相对于的车玻璃类。
- 再ICarFactory中添加创建CMirror的调用接口
- 在生产车子的工厂中(即对应销售员),添加一个新的服务“车玻璃”
就这样我的销售店越来越大,汽车类型越来越多,相应的维修产品也越来越多,然后我的钱也越来越多,我很开心,然后开心死了,这个文章也就结束了。
- 后记+代码
抽象工厂还有一些改编,我就不一一阐述了,如:
简单工厂+抽象工厂
反射+抽象工厂
反射+文件+抽象工厂
.......
// FactortyTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
#define interface struct
enum ECarType
{
e_carType_DaZhong = 0 ,
e_carType_BenChi,
e_carType_BMW,
};
//车子种类相关产品,包括
//基类CCar
//大众CDaZhongCar
//奔驰CBenChiCar
//宝马CBMWCar
class CCar
{
public:
virtual void createCar() {}
public:
string m_carName;
};
class CDaZhongCar :public CCar
{
public:
CDaZhongCar() { m_carName = "DaZhong Car"; }
~CDaZhongCar(){}
void createCar() { cout << "Create a DaZhong Car!" << endl; }
};
class CBenChiCar :public CCar
{
public:
CBenChiCar() { m_carName = "BenChi Car"; }
~CBenChiCar() {}
void createCar() { cout << "Create a BenChi Car!" << endl; }
};
class CBMWCar :public CCar
{
public:
CBMWCar() { m_carName = "BMW Car"; }
~CBMWCar() {}
void createCar() { cout << "Create a BMW Car!" << endl; }
};
//简单工厂模式下的工厂
//工厂负责返回实例和业务逻辑
//业务逻辑:根据输入进行分析,之后产生对应车子的实例对象
class CCarFactory
{
public:
CCar* createCar(ECarType carType);
};
CCar* CCarFactory::createCar(ECarType carType)
{
CCar* car = NULL;
switch (carType)
{
case e_carType_DaZhong:
{
car = new CDaZhongCar();
}break;
case e_carType_BenChi:
{
car = new CBenChiCar();
}break;
case e_carType_BMW:
{
car = new CBMWCar();
}break;
default: {}
}
return car;
}
//抽象工厂模式时的产品族
//此处为车玻璃
//包括基类、宝马对应的车玻璃类、大众对应的车玻璃类、奔驰对应的车玻璃类
class CMirror
{
public:
virtual void createMirror() {}
public:
string m_mirrorName;
};
class CDaZhongMirror :public CMirror
{
public:
CDaZhongMirror() { m_mirrorName = "DaZhong Mirror"; }
~CDaZhongMirror() {}
void createMirror() { cout << "Create a DaZhong Mirror!" << endl; }
};
class CBenChiMirror :public CMirror
{
public:
CBenChiMirror() { m_mirrorName = "BenChi Mirror"; }
~CBenChiMirror() {}
void createMirror() { cout << "Create a BenChi Mirror!" << endl; }
};
class CBMWMirror :public CMirror
{
public:
CBMWMirror() { m_mirrorName = "BMW Mirror"; }
~CBMWMirror() {}
void createMirror() { cout << "Create a BMW Mirror!" << endl; }
};
//简单工厂和抽象工厂下的工厂类
//包括提供获取CCar和CMirror接口的接口类
//包括专门生产大众相关、奔驰相关、宝马相关的对应工厂类
interface ICarFactory
{
//简单工厂只生产车子
virtual CCar* createCar() = 0;
//而抽象工厂还需要生产每种品牌的车子所对应的车玻璃等等(当然可能还有轮胎等等)
virtual CMirror* createMirror() = 0;
};
class CDaZhongCarFactory :public ICarFactory
{
public:
CCar* createCar() { return new CDaZhongCar(); }
CMirror* createMirror() { return new CDaZhongMirror(); }
};
class CBenChiCarFactory :public ICarFactory
{
public:
CCar* createCar() { return new CBenChiCar(); }
CMirror* createMirror() { return new CBenChiMirror(); }
};
class CBMWCarFactory :public ICarFactory
{
public:
CCar* createCar() { return new CBMWCar(); }
CMirror* createMirror() { return new CBMWMirror(); }
};
int main()
{
//简单工厂模式
//通过输入用户的选择,再工厂中进行逻辑,分析所需要产生的实例
CCarFactory cFactory;
CCar* car = cFactory.createCar(e_carType_BenChi);
if (car)
{
car->createCar();
}
//工厂和抽象工厂
//通过用自行创造对应的品牌工厂类
//再用对应的工厂类来产生所需要的实例
//工厂--只生产汽车
//抽象工厂--既生产汽车,也生产相关产品
ICarFactory *iCarFac = new CBMWCarFactory();
CCar* iCar = iCarFac->createCar();
CMirror* iMirror = iCarFac->createMirror();
if (iCar && iMirror)
{
iCar->createCar();
iMirror->createMirror();
}
}