三种工厂模式详解
我的相关博文:
别只知道策略模式+简单工厂,试试更香的策略模式+抽象工厂!
1. 简单工厂模式, 一图就看尽
涉及: 产品抽象类(即水果类) 、 工厂类、具体产品类(香蕉类、苹果类)
2.
工厂方法模式使用先来看一下,上截图:
工厂方法模式的实现:
3 class SingleCore // 抽象类,抽象的处理器类。 具体产品的基类
4 {
5 public:
6 virtual void Show() = 0;
7 };
8 class SingleCoreA:public SingleCore // 具体型号的处理器A 具体的产品类
9 {
10 public:
11 void Show()
12 {
13 cout << "单核处理器 A型" << endl;
14 }
15 };
16 class SingleCoreB:public SingleCore // 具体型号的处理器B 具体的产品类
17 {
18 public:
19 void Show()
20 {
21 cout << "单核处理器 B型" << endl;
22 }
23 };
24 class Factory // 抽象类, 工厂类 具体工厂的基类
25 {
26 public:
27 virtual SingleCore* CreateSingleCore() = 0;
28 };
29 class FactoryA:public Factory // 具体的工厂类 厂子1
30 {
31 public:
32 SingleCore* CreateSingleCore()
33 {
34 cout << "Create SingleCore A" << endl;
35 return new SingleCoreA(); // 厂子1生产A型CPU
36 }
37 };
38 class FactoryB:public Factory // 具体的工厂类 厂子2
39 {
40 public:
41 SingleCore* CreateSingleCore()
42 {
43 cout << "Create SingleCore B" << endl;
44 return new SingleCoreB(); //厂子2生产B型CPU
45 }
46 };
小结:
前者是简单工厂模式、后者是工厂方法模式。
简单工厂=》优点:使用简单。缺点:父类决定实例化哪个类, 在工厂内部直接创建产品,导致新增产品时就需要去修改工厂类的内部代码。
工厂方法=》优点:让子类决定实例化哪个类,将创建过程延迟到子类进行。 缺点:每增加一个新产品,就需要增加一个新产品的工厂。
个人见解:
感悟1.
感悟2.
纵观本例需要实现的功能:吃苹果、吃香蕉,吃是动词。苹果或香蕉是名词,
显然,如果我们能封装出一个吃函数,其参数是具体水果的标识(或称为ID,标识具体水果品种),那么用户使用时候会更加方便。
从本例子来看,简单工厂模式在使用的时候可以传入特定字符串,显然是简单工厂模式更加容易封装出符合此要求的函数,而工厂方法模式则不太容易满足此要求。
最后,我的态度是设计模式没有好坏,只有根据当前场景、程序员的需求,进行特定的挑选和使用。
3.抽象工厂模式
抽象工厂模式是一个创建型设计模式,它针对的是创建产品族,而不是单单一个产品。
说大白话,上面的工厂方法模式的示例代码,只维护了一个SingleCore类,也就是只有一个产品线。
如果是维护多个产品线的情况,例如有生产CPU,还有生产水果,还有输出语音控制(每种语音可视为一种产品,其抽象类则是获取对应的语音ID)等,
那么抽象的工厂类里就需要声明多个纯虚函数。
经过这样的简单修改,就可以创建产品族,这就成了抽象工厂模式了。所以,抽象工厂和工厂方法其实是极其类似的。
#include <iostream>
#include <string>
using namespace std;
// 点评shape类: 一条产品线下的产品,通常存在共性,也就是说,一个产品抽象类通常是需要的,而不是必须的。
class Shape
{
public:
virtual void draw()=0;
virtual ~Shape(){}
};
class Rectangle :public Shape
{
public:
void draw()
{
cout << "from rectangle"<<endl;
}
};
class Circle :public Shape
{
public:
void draw()
{
cout << "from circle"<< endl;
}
};
// 点评color类: 一条产品线下的产品,通常存在共性,也就是说,一个产品抽象类通常是需要的,而不是必须的。
class Color
{
public:
virtual void fill()=0;
virtual ~Color(){}
};
class Green:public Color
{
public:
void fill()
{
cout << "color green"<<endl;
}
};
class Red:public Color
{
public:
void fill()
{
cout << "color red"<<endl;
}
};
class AbFactory // 抽象工厂这里可以实现多个纯虚方法
{
public:
virtual Shape* createShape(string Shape)=0;
virtual Color* fillColor(string color)=0;
virtual ~AbFactory(){}
};
class ShapeFactory:public AbFactory
{
public:
Color* fillColor(string color)
{
return NULL;
}
Shape* createShape(string shape)
{
if(shape=="rectangle"){
return new Rectangle();
}
else if(shape == "circle")
{
return new Circle();
}
return NULL;
}
};
class ColorFactory:public AbFactory
{
public:
Color* fillColor(string color)
{
if(color=="green"){
return new Green();
}
else if(color == "red")
{
return new Red();
}
return NULL;
}
Shape* createShape(string shape)
{
return NULL;
}
};
int main(int argc, char *argv[])
{
AbFactory* abfactory; // 创建抽象工厂指针
abfactory = new ShapeFactory(); // 创建绘图工厂
Shape* shape = abfactory->createShape("rectangle"); //获取绘制矩形的工具(产品)
if(shape == NULL)
{
cout << "shape is NULL";
}
else
{
shape->draw(); // 使用绘制矩形的产品
}
delete shape;
delete abfactory;
abfactory = new ColorFactory(); // 创建喷漆工厂
Color* color = abfactory->fillColor("red"); //获取喷红漆的工具(产品)
if(color == NULL)
{
cout << "color is NULL";
}
else
{
color->fill(); // 使用喷红漆的产品
}
delete color;
delete abfactory;
return 0;
}
个人理解:
0. 封装了产品的创建,使得不需要知道具体是哪种产品,只需要知道是哪个工厂即可。这点是明显区分于简单工厂的。
1.抽象工厂类似总公司,负责规定并建立所有的产品线(即声明纯虚函数),原则上以后不允许再新增产品线,否则需要在该类内部新增纯虚函数,这破坏了开闭原则。
2.继承于抽象工厂类的具体工厂,根据需要可以选择性(部分或全部)实现产品线(即上述纯虚函数)来创建具体的产品。这是符合开闭原则的,因为此时新增工厂,并不需要修改已有的代码。
3. 创建一个具体产品的产品抽象类,具体产品类负责实现该产品抽象类。
抽象工厂模式可以创建产品组,即:不同子公司(具体工厂类)都严格按照产品线来生产产品,然而各自产品线的具体产品可以个性化实现, 同时,一条产品线下的产品,通常存在共性,也就是说,一个产品抽象类通常是需要的,而不是必须的。
小结: 抽象工厂模式,可以新增工厂(例如ColorFactory类),也可以新增具体产品(例如Rectangle类),但是不建议新增产品线,这会破坏开闭原则,
同时,产品抽象类的功能概念是与产品线的功能概念遥相呼应的存在,虽不是必须的,但通常是需要的。
文末:
抽象工厂,也可以参考 https://blog.csdn.net/konglongdanfo1/article/details/83380770 文章嘛 多看点好,不同的角度。
.