引言
在上篇文章中,讲解了简单工厂模式,文章末尾处可以发现,该模式是不符合开闭原则的,在新增多种同类功能时,需要修改原来的代码,这时候可根据业务的规模,来确定是否要更换设计模式。
简单介绍
工厂模式能够做到几乎不修改代码就能新增同类功能,相比于简单工厂而言,二者对于功能类的处理是一致的,抽象出功能的变化进行封装,对于工厂类则是将判断逻辑给拆分成具体的工厂类,由具体的工厂类再来产生具体的功能类对象,工厂模式具体的使用场景为:对于某个需求,调用者(使用者)知道自己需要使用哪个具体工厂来提供服务,就只需实例化该工厂,产生具体对象提供服务。一个工厂模式的UML类图如下:
改进与代码实现
通过上述讲解可知,只需要改进简单工厂模式中的工厂类即可,具体措施如下:由于工厂要产生不同的对象,因此需要把变化抽象出来,封装成一个接口,具体的工厂来实现该接口,工厂类定义如下:
class FactoryBase
{
public:
FactoryBase() {}
~FactoryBase() {}
virtual Product* GetProduct() = 0;
};
class AFactory : public FactoryBase
{
public:
AFactory() {}
~AFactory() {}
virtual Product* GetProduct()
{
return new ConcreteProductA();
}
};
class BFactory : public FactoryBase
{
public:
BFactory() {}
~BFactory() {}
virtual Product* GetProduct()
{
return new ConcreteProductB();
}
};
具体代码实现如下:
#include<iostream>
#include<string>
#include<memory>
using namespace std;
//简单工厂违背了开闭原则 拓展不方便
//将生产实际的类的判断 从工厂中分离 创建多个工厂来对应不同的产品
class Product
{
public:
virtual void MethodName()
{
//公共方法的实现
}
virtual void work() = 0;
//声明抽象业务方法
};
class ConcreteProductA : public Product
{
public:
void MethodName()
{
cout << "我是海尔牌-洗衣机." << endl;
}
void work()
{
//业务方法的实现
cout << "我是小海洗,我能洗刷刷..." << endl;
}
};
class ConcreteProductB : public Product
{
public:
void MethodName()
{
cout << "我是海尔牌-空调." << endl;
}
void work()
{
//业务方法的实现
cout << "我是小海空,我让你凉爽爽..." << endl;
}
};
class FactoryBase
{
public:
FactoryBase() {}
~FactoryBase() {}
virtual Product* GetProduct() = 0;
};
class AFactory : public FactoryBase
{
public:
AFactory() {}
~AFactory() {}
Product* GetProduct()
{
return new ConcreteProductA();
}
};
class BFactory : public FactoryBase
{
public:
BFactory() {}
~BFactory() {}
Product* GetProduct()
{
return new ConcreteProductB();
}
};
int main(void)
{
//增加产品时 只需要新增产品类与工厂类
//而简单工厂 会增加新产品的同时 修改工厂的代码
FactoryBase* factoryA = new AFactory();
FactoryBase* factoryB = new BFactory();
//智能指针托管
unique_ptr<Product>productA(std::move(factoryA->GetProduct()));//工厂A类创建对象
unique_ptr<Product>productB(std::move(factoryB->GetProduct()));//工厂B类创建对象
productA->MethodName();
productA->work();
productB->MethodName();
productB->work();
system("pause");
return 0;
}
可以看到,工厂模式更加便于拓展,增加一个新的功能,需要拓展增加两个类,利用多态带来的便利,客户端只需更改创建具体工厂的那一行语句;但这也是它的一大缺点,方便拓展,代价就是定义了两倍的类,由此可见,没有十全十美的设计模式和算法,着重提升了某方面,其它方面必定需要妥协。预告:下篇将讲解单例模式。