1. 工厂模式的定义:
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足 创建型模式中所要求的“创建与使用相分离”的特点。
按实际业务场景划分,工厂模式有 3 种不同的实现方式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。
我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。
在简单工厂模式中创建实例的方法通常为静态(static)方法,因此简单工厂模式(Simple Factory Pattern)又叫作静态工厂方法模式(Static Factory Method Pattern)。
简单来说,简单工厂模式有一个具体的工厂类,可以生成多个不同的产品,属于创建型设计模式。简单工厂模式不在 GoF 23 种设计模式之列。
简单工厂模式每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度,违背了“开闭原则”。
“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
2. 优点和缺点
2.1. 优点
- 工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
- 客户端无需知道所创建具体产品的类名,只需知道参数即可。
- 也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。
2.2 缺点
- 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
- 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
- 系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
- 简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
3. 应用场景
对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。
4. 模式的结构
简单工厂模式的主要角色如下:
- 简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
- 抽象产品(Product):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
具体产品(ConcreteProduct):是简单工厂模式的创建目标。
//抽象产品类
class AbstractProduct
{
public:
//抽象方法:
};
//具体产品类
class ConcreteProduct :public AbstractProduct
{
public:
//具体实现方法
};
class SimpleFactory
{
public:
AbstractProduct createProduct(string productName)
{
AbstractProduct pro = NULL;
if (productName == "ProductA"){
pro = new ProductA();
}
else if (productName == "ProductB"){
pro = new ProductB();
}
...
}
};
5. 模式的实现
5.1. 定义抽象产品类
class AbstractBallProduct
{
public:
virtual ~AbstractBallProduct()/* = default;*/ //default表示默认的析构函数
{
std::cout << "析构 Abstractball 对象" << std::endl;
}
/*
* 抽象方法
*/
virtual void productName() = 0;
virtual void productIntroduction() = 0;
virtual void productID(int id)
{
}
protected:
AbstractBallProduct() = default; //default表示默认的构造函数
};
5.2. 定义具体产品类
/定义具体产品类:篮球类
class BasketballProduct :public AbstractBallProduct
{
public:
BasketballProduct()
{
std::cout << "构造 Basketball 对象" << std::endl;
}
~BasketballProduct() /*override*/
{
std::cout << "析构 Basketball 对象" << std::endl;
}
//使用 override 有助于防止代码中出现意外的继承行为;
void productName() override
{
std::cout << "产品名称:Basketball" << std::endl;
}
void productIntroduction() override
{
std::cout << "产品介绍:Basketball" << std::endl;
}
//1.未使用override,表示productID是一个新的成员函数;
//2。使用override,表示productID是重写父类同名的成员函数
void productID(double id) /*override*/
{
std::cout << "产品编号:Basketball" << std::endl;
}
public:
private:
};
//定义具体产品类:足球类
class FootballProduct :public AbstractBallProduct
{
public:
FootballProduct()
{
std::cout << "构造 Football 对象" << std::endl;
}
~FootballProduct() /*override*/
{
std::cout << "析构 Football 对象" << std::endl;
}
void productName() override
{
std::cout << "产品名称:Football" << std::endl;
}
void productIntroduction() override
{
std::cout << "产品介绍:Football" << std::endl;
}
void productID(int id) override
{
std::cout << "产品编号:Football" << std::endl;
}
public:
private:
};
//定义具体产品类:排球类
class VolleyballProduct :public AbstractBallProduct
{
public:
VolleyballProduct()
{
std::cout << "构造 Volleyball 对象" << std::endl;
}
~VolleyballProduct() /*override*/
{
std::cout << "析构 Volleyball 对象" << std::endl;
}
void productName() override
{
std::cout << "产品名称:Volleyball" << std::endl;
}
void productIntroduction() override
{
std::cout << "产品介绍:Volleyball" << std::endl;
}
void productID(int id) override
{
std::cout << "产品编号:Volleyball" << std::endl;
}
public:
private:
};
5.3. 定义工厂类
//定义一个工厂类
class SimpleFactory
{
public:
SimpleFactory();
~SimpleFactory();
public:
static AbstractBallProduct* getProduct(const std::string& productName)
{
AbstractBallProduct* ptr = nullptr;
if ("Basketball" == productName)
{
ptr = new BasketballProduct();
}
else if ("Football" == productName)
{
ptr = new FootballProduct();
}
else if ("Volleyball" == productName)
{
ptr = new VolleyballProduct();
}
return ptr;
}
private:
};
SimpleFactory::SimpleFactory()
{
}
SimpleFactory::~SimpleFactory()
{
}
5.4. 主函数
int main()
{
//定义工厂类对象
AbstractBallProduct *product = nullptr;
product = SimpleFactory::getProduct("Basketball");
product->productName();
delete product;
for (size_t i = 0; i < 3; i++)
{
std::cout << std::endl;
}
product = SimpleFactory::getProduct("Football");
product->productIntroduction();
delete product;
for (size_t i = 0; i < 3; i++)
{
std::cout << std::endl;
}
product = SimpleFactory::getProduct("Volleyball");
product->productIntroduction();
delete product;
system("pause");
return 0;
}