工厂方法模式
- 工厂方法模式
- 主要组成部分
- 代码实现
- 工厂方法模式模式的 UML 图
- 工厂方法模式 UML 图解析
- 优点和缺点
- 适用场景
工厂方法模式
工厂方法模式是一种创建型设计模式,它通过定义一个接口用于创建对象,但由子类决定实例化哪个类。与简单工厂模式不同,工厂方法模式将对象的创建委托给子类,从而实现更好的扩展性和灵活性。
引入“工厂方法模式(实现意图):定义一个用于创建对象的接口,但由子类决定要实例化的类是哪一个。该模式使得某个类的实例化延迟到子类。
主要组成部分
- 产品接口(Product):定义了工厂方法所创建的对象的接口。
- 具体产品(ConcreteProduct):实现了产品接口的具体类。
- 工厂接口(Creator):声明了工厂方法,返回一个产品对象。
- 具体工厂(ConcreteCreator):实现了工厂接口,返回具体产品的实例。
代码实现
以下代码,主要用工厂方法模式创建不同类型的怪物对象:
#include <iostream>
#include <string>using namespace std;// 怪物父类
class Monster
{
public:Monster(int life, int magic, int attack) : m_life(life), m_magic(magic), m_attack(attack) {}virtual ~Monster() {} // 虚析构函数protected:int m_life; // 生命值int m_magic; // 魔法值int m_attack; // 攻击力
};// 亡灵类怪物
class M_Undead : public Monster
{
public:M_Undead(int life, int magic, int attack) : Monster(life, magic, attack){cout << "一只亡灵类怪物来到了这个世界" << endl;}// 其他代码略....
};// 元素类怪物
class M_Element : public Monster
{
public:M_Element(int life, int magic, int attack) : Monster(life, magic, attack){cout << "一只元素类怪物来到了这个世界" << endl;}// 其他代码略....
};// 机械类怪物
class M_Mechanic : public Monster
{
public:M_Mechanic(int life, int magic, int attack) : Monster(life, magic, attack){cout << "一只机械类怪物来到了这个世界" << endl;}// 其他代码略....
};// 工厂方法模式
// 所有工厂类的父类
class M_ParFactory
{
public:virtual Monster* createMonster() = 0; // 纯虚函数virtual ~M_ParFactory() {} // 虚析构函数
};// 亡灵类怪物工厂
class M_UndeadFactory : public M_ParFactory
{
public:virtual Monster* createMonster(){return new M_Undead(300, 50, 80); // 创建亡灵类怪物}
};// 元素类怪物工厂
class M_ElementFactory : public M_ParFactory
{
public:virtual Monster* createMonster(){return new M_Element(200, 80, 100); // 创建元素类怪物}
};// 机械类怪物工厂
class M_MechanicFactory : public M_ParFactory
{
public:virtual Monster* createMonster(){return new M_Mechanic(400, 0, 110); // 创建机械类怪物}
};// 全局创建怪物对象的函数
Monster* Gbl_CreateMonster(M_ParFactory* factory)
{return factory->createMonster(); // 根据工厂创建怪物
}// 创建怪物工厂子类模板
template <typename T>
class M_ChildFactory : public M_ParFactory
{
public:virtual Monster* createMonster() {return new T(300, 50, 80); // 创建具体类型的怪物}
};// 使用示例
int main()
{// 使用具体工厂创建怪物M_ParFactory* undeadFactory = new M_UndeadFactory();Monster* undead = Gbl_CreateMonster(undeadFactory);delete undead; // 释放内存delete undeadFactory;M_ParFactory* elementFactory = new M_ElementFactory();Monster* element = Gbl_CreateMonster(elementFactory);delete element; // 释放内存delete elementFactory;M_ParFactory* mechanicFactory = new M_MechanicFactory();Monster* mechanic = Gbl_CreateMonster(mechanicFactory);delete mechanic; // 释放内存delete mechanicFactory;// 使用模板工厂创建怪物M_ChildFactory<M_Undead> undeadChildFactory;Monster* undeadChild = Gbl_CreateMonster(&undeadChildFactory);delete undeadChild; // 释放内存return 0;
}
工厂方法模式模式的 UML 图
工厂方法模式 UML 图解析
- 类关系
Monster
:抽象基类,定义了怪物的基本属性(如m_life
、m_magic
、m_attack
)。M_Undead
、M_Element
、M_Mechanic
:具体类,继承自Monster
,实现不同类型的怪物。
- 工厂类
M_ParFactory
:抽象工厂类,定义了创建怪物的接口createMonster
。M_UndeadFactory
、M_ElementFactory
、M_MechanicFactory
:具体工厂类,继承自M_ParFactory
,分别负责创建不同类型的怪物。M_ChildFactory
:模板工厂类,能够创建任意类型的怪物,提供更灵活的创建方式。
- 稳定部分:
Gbl_CreateMonster
函数依赖的Monster
类和M_ParFactory
类属于稳定部分,不需要更改。
- 变化部分:
M_UndeadFactory
、M_ElementFactory
、M_MechanicFactory
类以及具体怪物类(如M_Undead
、M_Mechanic
)属于变化部分。Gbl_CreateMonster
函数不依赖于这些变化部分。
- 扩展新类型:
- 当需要引入新怪物类型(例如
M_Beast
)时,无需更改Gbl_CreateMonster
函数或修改MonsterFactory
的createMonster
方法。只需创建一个继承自Monster
的新类M_Beast
和一个继承自M_ParFactory
的新工厂类M_BeastFactory
,这符合开闭原则:对扩展开放,对修改关闭。
- 当需要引入新怪物类型(例如
- 隐藏实现细节:
- 如果
M_ParFactory
及其子类由第三方开发,工厂方法模式可以有效隐藏具体怪物类(如M_Undead
、M_Element
、M_Mechanic
),避免暴露给开发者。
- 如果
- 接口扩展:
M_ParFactory
的接口可以根据需要扩展,例如增加对 NPC(非玩家角色,如商人、路人等)的创建支持,或为createMonster
提供默认实现。
- 增加工厂类的代价:
- 增加新的工厂类是工厂方法模式的必然代价,但这为系统的灵活性和可扩展性提供了保障。
优点和缺点
- 优点:
- 符合开闭原则:新增产品时,只需创建新的产品类和相应的工厂类,无需修改现有代码。
- 减少耦合:客户端代码与具体产品类解耦,依赖于抽象工厂接口,增强了系统的灵活性。
- 扩展性强:可以方便地扩展新的产品类型,适合复杂系统的需求变化。
- 提高代码可读性:通过明确的工厂类和产品类的分离,代码结构更加清晰。
- 缺点:
- 类的数量增加:每新增一种产品都需要创建相应的工厂类,可能导致类的数量剧增,增加系统复杂性。
- 实现复杂性:对于简单产品的创建,工厂方法模式可能显得过于复杂,增加不必要的开销。
- 难以管理:如果产品种类过多,可能导致工厂类的管理变得困难。
适用场景
- 产品族:需要创建一系列相关或相互依赖的对象时,工厂方法模式非常适合。
- 产品类型变化频繁:当产品类型经常变化,且需要动态地扩展新产品时,工厂方法模式提供了良好的灵活性。
- 需要解耦的系统:当系统需要将对象创建与使用分离时,工厂方法模式可以有效降低耦合度。
- 复杂对象的创建:当对象的创建过程复杂,且可能涉及多个步骤时,工厂方法模式可以封装这些复杂性。