概述
简单工厂模式并不是GoF的23种设计模式之一,但它是一种常见的编程惯用法,用于简化对象的创建过程。简单工厂模式属于创建型模式的一种,提供了一种创建对象的最佳方式。
其核心思想是:定义一个负责创建其他类的实例的类。这个负责创建的类,通常被称为"管理类"或"工厂类",会根据传入的参数来决定应该创建哪一个具体的类。简单工厂模式将对象的创建和使用分离,客户端代码不需要知道具体的产品类名,只需要知道所需产品的类型或标识符即可。
自动售货机是运用简单工厂模式的一个例子:它接受硬币或纸币,并根据用户的选择提供特定的商品。这里,自动售货机扮演了工厂的角色,它根据用户的输入(商品代码)来决定分发哪一种商品。
基本原理
简单工厂模式的基本原理是:通过一个专门的工厂类来封装对象创建的逻辑。它提供了一种方式,使得客户端代码可以在不知道具体产品类的情况下创建产品实例。简单工厂模式包括如下三个核心组件。
1、工厂类。包含静态方法或实例方法用于创建产品对象,这个方法通常接收一些参数(枚举或字符串),用来决定应该创建哪种类型的产品。
2、产品接口。定义了所有具体产品必须实现的方法,它代表了所有可能被创建的对象的共同接口或者基类。
3、具体产品类。实现了产品接口的具体类,每个具体产品类都代表一种可以被创建的实际对象。
基于上面的核心组件,简单工厂模式的实现主要有以下四个步骤。
1、客户端调用工厂类中的创建方法,并传入必要的参数,以指示希望创建哪一种类型的产品。
2、工厂类根据传入的参数,使用if-else或者switch-case语句,判断应该实例化哪一个具体的产品类。
3、工厂类创建并返回相应的产品对象给客户端。
4、客户端接收到产品对象后,可以通过产品接口与该对象进行交互,而无需关心具体的实现细节。
实战解析
在下面的实战代码中,我们使用简单工厂模式创建了一个图形产品的工厂。
CShape是所有图形产品的公共接口和基类,定义了一个纯虚函数Draw用于绘制图形。CCircle和CRectangle是两个具体的产品类,它们各自实现了Draw函数,以提供具体的绘图逻辑。
CShapeFactory类包含一个静态方法CreateShape,它根据传入的枚举参数决定创建哪种类型的图形对象,并返回指向新创建对象的指针。这种方法使得客户端代码不需要关心具体的图形类是如何创建的,从而简化了对象创建的过程,并降低了耦合度。
在main函数中,我们通过传递不同的枚举值给CreateShape方法来创建不同类型的图形对象,并调用其Draw方法进行绘制。
cpp
#include <iostream>
using namespace std;
// 定义产品接口和基类,所有具体产品都必须实现此接口
class CShape
{
public:
virtual void Draw() const = 0;
virtual ~CShape() {}
};
// 具体产品CCircle
class CCircle : public CShape
{
public:
void Draw() const override
{
cout << "Draw Circle" << endl;
}
};
// 具体产品CRectangle
class CRectangle : public CShape
{
public:
void Draw() const override
{
cout << "Draw Rectangle" << endl;
}
};
// 产品类型枚举
enum IShapeType { None, Circle, Rectangle };
// 工厂类
class CShapeFactory {
public:
static CShape* CreateShape(IShapeType type)
{
switch (type)
{
case Circle:
return new CCircle();
case Rectangle:
return new CRectangle();
default:
return NULL;
}
}
};
int main()
{
// 客户端代码
CShape* pCircle = CShapeFactory::CreateShape(Circle);
pCircle->Draw();
delete pCircle;
CShape* pRectangle = CShapeFactory::CreateShape(Rectangle);
pRectangle->Draw();
delete pRectangle;
return 0;
}
总结
简单工厂模式简化了对象的创建,客户端只需要知道所需的对象类型,不需要了解对象创建的具体过程。由于将对象创建的逻辑集中在一个地方,便于维护和扩展,代码复用性高。同时,简单工厂模式还降低了客户端代码与具体产品类之间的耦合度,符合依赖倒置原则。
但简单工厂模式也有两个缺点:一是违背开闭原则,如果需要添加新的产品类型,则必须修改工厂类的逻辑,这违反了"对扩展开放,对修改关闭"的设计思想;二是工厂类职责过重,当产品种类增多时,工厂类可能会变得非常庞大且难以管理。