简单工厂模式的弊端
在上一节简单工厂模式中,创建了一个工厂类,用于生产需要的对象,但是这种方式有一个弊端,它违反了设计模式中的开放-封闭原则,先来看相关的代码。
// 恶魔果实工厂类
enum class Type:char{
SHEEP, LION, BAT};
class SmileFactory
{
public:
SmileFactory() {
}
~SmileFactory() {
}
AbstractSmile* createSmile(Type type)
{
AbstractSmile* ptr = nullptr;
switch (type)
{
case Type::SHEEP:
ptr = new SheepSmile;
break;
case Type::LION:
ptr = new LionSmile;
break;
case Type::BAT:
ptr = new BatSmile;
break;
default:
break;
}
return ptr;
}
};
在上面的工厂函数中需要生成三种人造恶魔果实,现在如果想要生成更多,那么就需要在工厂函数的switch语句中添加更多的case,很明显这违背了封闭原则,也就意味着需要基于开放原则来解决这个问题。
使用工厂模式可以很完美的解决上述的问题,简单工厂模式是只有一个工厂类,而工厂模式是有很多的工厂类:
一个基类,包含一个虚工厂函数,用于实现多态。
多个子类,重写父类的工厂函数。每个子工厂类负责生产一种恶魔果实,这相当于再次解耦,将工厂类的职责再次拆分、细化,如果要生产新品种的恶魔果实,那么只需要添加对应的工厂类,无需修改原有的代码。
工厂模式
我们先修改一下简单工厂模式中工厂类相关的代码:
// 恶魔果实工厂类
class AbstractFactory
{
public:
virtual AbstractSmile* createSmile() = 0;
virtual ~AbstractFactory() {
}
};
class SheepFactory : public AbstractFactory
{
public:
AbstractSmile* createSmile() override
{
return new SheepSmile;
}
~SheepFactory()
{
cout << "释放 SheepFactory 类相关的内存资源" << endl;
}
};
class LionFactory : public AbstractFactory
{
public:
AbstractSmile* createSmile() override
{
return new LionSmile;
}
~LionFactory()
{
cout << "释放 LionFactory 类相关的内存资源" << endl;
}
};
class BatFactory : public AbstractFactory
{
public:
AbstractSmile* createSmile() override
{
return new BatSmile;
}
~BatFactory()
{
cout << "释放 BatFactory 类相关的内存资源" << endl;
}
};
通过示例代码可以看到,每个工厂类其实都不复杂,在每个子工厂类中也只是重写了父类的工厂方法而已,每个子工厂类生产一种恶魔果实,但是工厂函数的返回值确是恶魔果实类的基类类型,相当于是使用父类指针指向了子类对象,此处也是用到了多态。通过这样的处理,工厂函数也就不再需要参数了。
根据简单工厂模式的代码和上面的修改就可以把工厂模式的UML类图画出来了:
完整的代码应该是这样的:
#include <iostream>
using namespace std;
class AbstractSmile
{
public:
virtual void transform() = 0;
virtual void ability() = 0;
virtual ~AbstractSmile() {
}
};
// 人造恶魔果实· 绵羊形态
class SheepSmile : public AbstractSmile
{
public:
void transform() override
{
cout << "变成人兽 -- 山羊人形态..." << endl;
}
void ability() override
{
cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl;
}
};
// 人造恶魔果实· 狮子形态
class LionSmile : public AbstractSmile
{
public:
void transform() override
{
cout << "变成人兽 -- 狮子人形态..." << endl;
}
void ability() override
{
cout << "火遁· 豪火球之术..." << endl;
}
};
class BatSmile : public AbstractSmile
{
public:
void transform() override
{
cout << "变成人兽 -- 蝙蝠人形态..." << endl;
}
void ability() override
{
cout << "声纳引箭之万剑归宗..." << endl;
}
};
// 恶魔果实工厂类
class AbstractFactory
{
public:
virtual AbstractSmile* createSmile() = 0;
virtual ~AbstractFactory() {
}
};
class SheepFactory : public AbstractFactory
{
public:
AbstractSmile* createSmile() override
{
return new SheepSmile;
}
~SheepFactory()
{
cout << "释放 SheepFactory 类相关的内存资源" << endl;
}
};
class LionFactory : public AbstractFactory
{
public:
// 工厂函数
AbstractSmile* createSmile() override
{
return new LionSmile;
}
~LionFactory()
{
cout << "释放 LionFactory 类相关的内存资源" << endl;
}
};
class BatFactory : public AbstractFactory
{
public:
// 工厂函数
AbstractSmile* createSmile() override
{
return new BatSmile;
}
~BatFactory()
{
cout << "释放 BatFactory 类相关的内存资源" << endl;
}
};
int main()
{
AbstractFactory* factory = new BatFactory;
AbstractSmile* obj = factory->createSmile();
obj->transform();
obj->ability();
return 0;
}
在main()函数中的这句代码是实例化了一个生成蝙蝠恶魔果实的工厂对象:
AbstractFactory* factory = new BatFactory;
在真实的项目场景中,要生成什么类型的恶魔果实其实是通过客户端的操作界面控制的,它对应的可能是一个按钮或者是一个选择列表,用户做出了选择,程序就可以根据该需求去创建对应的工厂对象,最终将选择的恶魔果实生产出来。