抽象工厂模式
抽象工厂模式
抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。它通常用于需要创建多个产品族的场景。
引入"抽象工厂模式"设计模式的定义(实现意图):提供一个接口,让该接口负责创建一系列相关或者相互依赖的对象,而无须指定它们具体的类。
主要组成部分
- 抽象工厂(AbstractFactory):定义创建抽象产品的接口。它声明了用于创建不同类型产品的方法。
- 具体工厂(ConcreteFactory):实现抽象工厂接口,创建具体产品。每个具体工厂负责生成一组相关的具体产品。
- 抽象产品(AbstractProduct):定义产品的接口。它为具体产品提供了一个公共的接口。
- 具体产品(ConcreteProduct):实现抽象产品接口的具体类。每个具体产品对应于一个具体工厂。
代码实现
以下是使用抽象工厂模式创建不同类型的怪物对象的代码示例:
cpp
#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_Swamp : public Monster {
public:
M_Undead_Swamp(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个沼泽的亡灵类怪物来到了这个世界" << endl;
}
};
// 沼泽元素类怪物
class M_Element_Swamp : public Monster {
public:
M_Element_Swamp(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个沼泽的元素类怪物来到了这个世界" << endl;
}
};
// 沼泽机械类怪物
class M_Mechanic_Swamp : public Monster {
public:
M_Mechanic_Swamp(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个沼泽的机械类怪物来到了这个世界" << endl;
}
};
// 山脉亡灵类怪物
class M_Undead_Mountain : public Monster {
public:
M_Undead_Mountain(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个山脉的亡灵类怪物来到了这个世界" << endl;
}
};
// 山脉元素类怪物
class M_Element_Mountain : public Monster {
public:
M_Element_Mountain(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个山脉的元素类怪物来到了这个世界" << endl;
}
};
// 山脉机械类怪物
class M_Mechanic_Mountain : public Monster {
public:
M_Mechanic_Mountain(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个山脉的机械类怪物来到了这个世界" << endl;
}
};
// 城镇亡灵类怪物
class M_Undead_Town : public Monster {
public:
M_Undead_Town(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个城镇的亡灵类怪物来到了这个世界" << endl;
}
};
// 城镇元素类怪物
class M_Element_Town : public Monster {
public:
M_Element_Town(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个城镇的元素类怪物来到了这个世界" << endl;
}
};
// 城镇机械类怪物
class M_Mechanic_Town : public Monster {
public:
M_Mechanic_Town(int life, int magic, int attack) : Monster(life, magic, attack) {
cout << "一个城镇的机械类怪物来到了这个世界" << endl;
}
};
// 所有工厂类的父类
class M_ParFactory {
public:
virtual Monster* createMonster_Undead() = 0; // 创建亡灵类怪物
virtual Monster* createMonster_Element() = 0; // 创建元素类怪物
virtual Monster* createMonster_Mechanic() = 0; // 创建机械类怪物
virtual ~M_ParFactory() {} // 虚析构函数
};
// 沼泽地区的工厂
class M_Factory_Swamp : public M_ParFactory {
public:
virtual Monster* createMonster_Undead() override {
return new M_Undead_Swamp(300, 50, 120); // 创建沼泽亡灵类怪物
}
virtual Monster* createMonster_Element() override {
return new M_Element_Swamp(200, 80, 110); // 创建沼泽元素类怪物
}
virtual Monster* createMonster_Mechanic() override {
return new M_Mechanic_Swamp(400, 0, 90); // 创建沼泽机械类怪物
}
};
// 山脉地区的工厂
class M_Factory_Mountain : public M_ParFactory {
public:
virtual Monster* createMonster_Undead() override {
return new M_Undead_Mountain(300, 50, 80); // 创建山脉亡灵类怪物
}
virtual Monster* createMonster_Element() override {
return new M_Element_Mountain(200, 80, 100); // 创建山脉元素类怪物
}
virtual Monster* createMonster_Mechanic() override {
return new M_Mechanic_Mountain(600, 0, 110); // 创建山脉机械类怪物
}
};
// 城镇的工厂
class M_Factory_Town : public M_ParFactory {
public:
virtual Monster* createMonster_Undead() override {
return new M_Undead_Town(300, 50, 80); // 创建城镇亡灵类怪物
}
virtual Monster* createMonster_Element() override {
return new M_Element_Town(200, 80, 100); // 创建城镇元素类怪物
}
virtual Monster* createMonster_Mechanic() override {
return new M_Mechanic_Town(400, 0, 110); // 创建城镇机械类怪物
}
};
// 使用示例
int main() {
M_ParFactory* factory = new M_Factory_Swamp();
Monster* undead = factory->createMonster_Undead();
Monster* element = factory->createMonster_Element();
Monster* mechanic = factory->createMonster_Mechanic();
// 释放内存
delete undead;
delete element;
delete mechanic;
delete factory;
return 0;
}
抽象工厂模式模式的 UML 图
抽象工厂模式 UML 图解析
- 类与类之间的关系 :
Monster
类是所有具体怪物类的父类,子类(如M_Undead_Swamp
、M_Element_Swamp
、M_Mechanic_Swamp
等)通过实线箭头与父类连接,箭头指向Monster
类,表示继承关系。M_ParFactory
是抽象工厂类,定义了创建不同类型怪物的接口。具体工厂类(如M_Factory_Swamp
、M_Factory_Mountain
、M_Factory_Town
)通过实线箭头与M_ParFactory
类连接,表示继承关系。
- 依赖关系 :
- 具体工厂类(如
M_Factory_Swamp
等)与具体怪物类(如M_Undead_Swamp
等)之间存在虚线箭头,表示依赖关系。具体工厂类负责实例化具体怪物类的对象,箭头指向被实例化的类。
- 具体工厂类(如
- 稳定与变化部分 :
- 稳定部分 :
Monster
类和M_ParFactory
类是稳定部分,不需要频繁修改。 - 变化部分 :具体怪物类(如
M_Undead_Swamp
、M_Element_Swamp
等)和具体工厂类(如M_Factory_Swamp
等)属于变化部分。当需要添加新类型的怪物时,只需增加新的具体工厂类和具体怪物类,而不需要修改稳定部分。
- 稳定部分 :
- 扩展性 :
- 当需要引入新类型的怪物(如
M_Beast
),只需创建一个新的具体工厂类(如M_Factory_Beast
)和对应的怪物类(如M_Beast
),而不需要更改现有的工厂接口。这符合开闭原则:对扩展开放,对修改关闭。
- 当需要引入新类型的怪物(如
- 隐藏实现细节 :
- 如果
M_ParFactory
类及其具体实现由第三方开发,开发者只需通过抽象工厂接口与工厂交互,而无需了解具体的怪物类(如M_Undead_Swamp
等),实现了对具体实现的隐藏。
- 如果
- 接口扩展 :
M_ParFactory
中的接口可以根据需要进行扩展,例如新增创建其他类型对象的方法(如 NPC),使得工厂能够支持更丰富的对象创建。
优点和缺点
优点:
- 解耦合:客户端代码与具体产品的实现解耦,便于维护和扩展。修改产品的实现不会影响到客户端。
- 一致性:可以确保一组产品的一致性,避免在创建产品时出现不匹配的情况。例如,创建一个特定类型的怪物时,工厂会确保所有相关的属性和行为都符合预期。
- 易于扩展:新增产品类型时,只需扩展工厂类和相应的产品类,而无需修改现有代码,符合开闭原则。
- 隔离变化:将产品的创建逻辑集中在工厂中,减少了产品类之间的依赖,便于管理和控制变化。
缺点:
- 系统复杂性增加:引入抽象工厂模式会增加系统的复杂性,特别是在产品种类较多时,工厂类和产品类的数量也会增加。
- 维护成本:随着产品族的增加,维护抽象工厂及其子类的成本可能会提升,特别是当需要对多个工厂进行修改时。
- 难以支持新产品:如果需要支持新类型的产品,可能需要修改现有的工厂接口和实现,这可能导致较大的代码变动。
- 运行时开销:由于使用了多层抽象,可能会引入一定的运行时开销,尤其是在频繁创建对象的场景中。
适用场景
- 产品族的创建:当系统需要创建一组相关或相互依赖的产品时,使用抽象工厂模式可以确保产品的一致性和完整性。
- 需要解耦的系统:当需要将产品的创建与使用分离,减少系统之间的耦合度时,抽象工厂模式是一个理想的选择。
- 需要支持多个产品变体:在需要支持不同变体的情况下,例如不同地区的怪物、不同类型的用户界面组件等,抽象工厂模式可以有效管理这些变体。
- 需要扩展产品类型:当系统需要频繁扩展新产品类型时,抽象工厂模式提供了良好的扩展机制,符合开闭原则。
- 框架设计:在设计框架或库时,抽象工厂模式可以为用户提供灵活的产品创建接口,用户可以根据需要实现具体的工厂类。