1.概要
2.内容
当前:抽象工厂
说明:抽象工厂就是创建一系列的对象,就像是一个零部件的加工场。比如给车提供零部件可以提供轮胎,底盘,门等。如果为教室提供配件,可以提供,墙、门、窗、黑板,桌椅等。就是对一系列的产品提供风格控制。于其他模式的做对比,其实和创建型模式挺像的,创建这模式提供的是一系列的创建步骤,如果这一系列的创建步骤就是创建这个产品分分别的部件,那么和抽象工厂的价值几乎就相同的了,如果真的是这样,创建者模式的价值也是控制一系列产品的风格。但是通常创建者提供的一系列函数更强调时间上的顺序。也就是说创建在创建产品部件的过程中是有先后顺序的。
需求:坦克大战
创建两种坦克
坦克类型 | 射程 | 速度 |
b70 | 70米 | 时/70公里 |
b50 | 50米 | 时/50公里 |
类图
说明
看到这张类库,可以明显的看到,这里和工厂模式的坦克大战比,是把两个机能,发射和速度当做抽象工厂中的一系列产品。
代码(c++实现)
#include <iostream>
#include <string>
using namespace std;
class Function{
public:
string mFunction;
Function(string str){
mFunction = str;
}
void exe(){
cout<<mFunction<<"\n";
}
};
//抽象层
class AbstractShot{
public:
virtual void fun()=0;
};
class AbstractRun{
public:
virtual void fun()=0;
};
class AbstractFactory{
public:
virtual AbstractShot& createShot()=0;
virtual AbstractRun& createRun()=0;
};
//实施层
class B70Shot: public AbstractShot{
public:
virtual void fun(){
Function function("B70Shot:射程70");
function.exe();
}
};
class B50Shot: public AbstractShot{
public:
virtual void fun(){
Function function("B50Shot:射程50");
function.exe();
}
};
class B70Run: public AbstractRun{
public:
virtual void fun(){
Function function("B70Run:速度70");
function.exe();
}
};
class B50Run: public AbstractRun{
public:
virtual void fun(){
Function function("B50Run:速度50");
function.exe();
}
};
class B70Factory:public AbstractFactory{
public:
virtual AbstractShot& createShot(){
return *(new B70Shot());
}
virtual AbstractRun& createRun(){
return *(new B70Run());
}
};
class B50Factory:public AbstractFactory{
public:
virtual AbstractShot& createShot(){
return *(new B50Shot());
}
virtual AbstractRun& createRun(){
return *(new B50Run());
}
};
// 客户端
class Client{
public:
static void main(){
B70Factory b70;
AbstractFactory& f = b70;
AbstractShot& s = f.createShot();
AbstractRun& r = f.createRun();
s.fun();
r.fun();
}
};
//客户端调用
int main()
{
Function function("抽象工厂模式演示");
function.exe();
Client::main();
//看代码不用考虑以下内容
int cin_a;
cin>>cin_a;
return 0;
}
3.关联链接
4.关联知识
1.
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,用于创建一系列相关或依赖的对象,而无需指定它们的具体类。它通过定义一个抽象接口来封装对象的创建过程,使得客户端代码与具体实现解耦。
核心思想
- 产品族:将一组相关的产品(属于同一主题)组合在一起,形成产品族。
- 抽象工厂:声明创建抽象产品的方法,具体子类实现这些方法以生成具体产品。
- 客户端依赖抽象:客户端通过抽象接口操作产品,无需关心具体实现。
结构组成
-
抽象产品(AbstractProduct)
定义产品的抽象接口,如Button
、TextField
。 -
具体产品(ConcreteProduct)
实现抽象产品的接口,如WindowsButton
、MacButton
。 -
抽象工厂(AbstractFactory)
声明创建抽象产品的方法,如createButton()
、createTextField()
。 -
具体工厂(ConcreteFactory)
实现抽象工厂的方法,返回具体产品实例,如WindowsFactory
、MacFactory
。 -
客户端(Client)
通过抽象工厂获取产品实例,仅依赖抽象类型。
适用场景
- 需要创建多个产品族,且希望系统独立于产品的创建、组合和表示。
- 系统需要支持多种界面风格(如暗黑主题、明亮主题)。
- 需要兼容多个数据库(如 MySQL、PostgreSQL)的驱动和连接。
- 产品族需要一起使用(如 UI 组件的按钮、文本框必须风格统一)。
示例代码(Java)
// 抽象产品:按钮
interface Button {
void render();
}
// 具体产品:Windows 按钮
class WindowsButton implements Button {
@Override
public void render() {
System.out.println("渲染 Windows 风格按钮");
}
}
// 具体产品:Mac 按钮
class MacButton implements Button {
@Override
public void render() {
System.out.println("渲染 Mac 风格按钮");
}
}
// 抽象产品:文本框
interface TextField {
void render();
}
// 具体产品:Windows 文本框
class WindowsTextField implements TextField {
@Override
public void render() {
System.out.println("渲染 Windows 风格文本框");
}
}
// 具体产品:Mac 文本框
class MacTextField implements TextField {
@Override
public void render() {
System.out.println("渲染 Mac 风格文本框");
}
}
// 抽象工厂
interface GUIFactory {
Button createButton();
TextField createTextField();
}
// 具体工厂:Windows 工厂
class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextField createTextField() {
return new WindowsTextField();
}
}
// 具体工厂:Mac 工厂
class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextField createTextField() {
return new MacTextField();
}
}
// 客户端代码
public class Application {
private Button button;
private TextField textField;
public Application(GUIFactory factory) {
button = factory.createButton();
textField = factory.createTextField();
}
public void render() {
button.render();
textField.render();
}
public static void main(String[] args) {
// 使用 Windows 风格
Application app1 = new Application(new WindowsFactory());
app1.render();
// 使用 Mac 风格
Application app2 = new Application(new MacFactory());
app2.render();
}
}
优点
- 隔离具体类:客户端无需知道具体产品的类名。
- 易于交换产品族:只需更换工厂即可切换整个产品族。
- 保证兼容性:同一工厂创建的产品族必然兼容。
缺点
- 扩展复杂:新增产品族需修改抽象工厂接口及所有具体工厂。
- 产品族限制:难以支持跨产品族的产品组合(如混合使用 Windows 按钮和 Mac 文本框)。
与工厂方法模式的区别
特性 | 抽象工厂 | 工厂方法 |
---|---|---|
创建对象 | 一族相关对象 | 单一对象 |
工厂角色 | 多个具体工厂 | 一个具体工厂 |
扩展性 | 新增产品族困难 | 新增产品容易 |
典型场景 | 换肤、数据库驱动 | 日志记录器、解析器 |
总结
抽象工厂模式通过封装产品族的创建逻辑,使得系统能够灵活地切换产品族,同时保持客户端代码的简洁和稳定。适用于需要统一管理多产品依赖关系的场景,但需谨慎权衡扩展性需求。
2.与其他模式配合
抽象工厂模式在创建型模式中具有重要地位,其价值体现在对复杂对象创建场景的抽象和封装,尤其适用于需要管理产品族的场景。以下从地位、核心价值及与其他模式的协作价值展开分析:
一、抽象工厂在创建型模式中的地位
-
高级抽象层
抽象工厂是创建型模式中的“战略层”工具,解决产品族(一组相关产品)的创建问题,而非单个对象的创建。相较于工厂方法(战术层,关注单一产品),它提供更宏观的抽象。 -
解耦的终极形态
通过隔离具体产品类,抽象工厂使客户端完全依赖抽象接口,彻底消除对实现细节的耦合,是依赖倒置原则(DIP)的典范实现。 -
框架级设计基础
许多框架(如GUI工具包、ORM框架)通过抽象工厂实现跨平台/数据库的支持,例如Java的javax.xml.parsers.DocumentBuilderFactory
。
二、抽象工厂的核心价值
-
产品族一致性保证
确保同一工厂创建的产品族在风格、兼容性上一致(如Windows控件族与Mac控件族),避免混搭导致的问题。 -
系统扩展性增强
新增产品族只需扩展工厂接口和实现,无需修改现有客户端代码,符合开闭原则(OCP)。 -
替换实现的灵活性
通过切换工厂即可更换整个产品族(如从MySQL切换到PostgreSQL),提升系统可配置性和可测试性。
三、与其他模式配合的特殊价值
1. 与工厂方法模式协作
- 场景:当产品族中的某些产品需要独立扩展时。
- 协作方式:
抽象工厂定义产品族接口,工厂方法实现具体产品的创建。例如:// 抽象工厂定义产品族 interface GUIFactory { Button createButton(); // 委托给工厂方法 TextField createTextField(); // 委托给工厂方法 } // 具体工厂使用工厂方法 class WindowsFactory implements GUIFactory { @Override public Button createButton() { return new WindowsButton(); // 直接实例化或调用工厂方法 } // ... }
- 价值:结合两种模式的优势,既保证产品族一致性,又为单个产品提供扩展点。
2. 与建造者模式协作
- 场景:产品族中的对象需要复杂构造过程(如分步骤构建)。
- 协作方式:
抽象工厂创建建造者,建造者负责具体构造逻辑。例如:// 抽象工厂创建建造者 interface CarFactory { CarBuilder createSportsCarBuilder(); } // 建造者定义复杂构造步骤 interface CarBuilder { void buildEngine(); void buildBody(); Car getResult(); }
- 价值:将对象创建分为“选择产品族”(工厂)和“构造细节”(建造者),应对复杂对象的分步骤创建。
3. 与原型模式协作
- 场景:产品族的创建成本较高,需通过克隆优化性能。
- 协作方式:
抽象工厂返回原型对象的克隆实例。例如:// 抽象工厂返回原型 interface ShapeFactory { Shape createCircle(); // 返回原型实例的克隆 } // 具体工厂使用原型 class PrototypeFactory implements ShapeFactory { private static final Circle prototype = new Circle(); @Override public Shape createCircle() { return prototype.clone(); } }
- 价值:避免重复创建昂贵对象,提升性能。
4. 与依赖注入(DI)框架协作
- 场景:在框架中管理对象生命周期和依赖关系。
- 协作方式:
依赖注入容器充当抽象工厂,根据配置动态提供产品族实例。例如Spring的@Autowired
注入不同数据源的ConnectionFactory
。 - 价值:实现运行时动态切换产品族,提升系统可配置性和可测试性。
四、总结:特殊价值的核心逻辑
抽象工厂的特殊价值在于其“接口隔离”与“产品族封装”能力,与其他模式配合时:
- 分工明确:抽象工厂负责选择产品族,其他模式负责具体对象的创建或构造。
- 扩展正交:通过组合模式,可以在不破坏现有结构的前提下,独立扩展产品族或单个产品的创建逻辑。
- 框架友好:其设计思想直接支撑了现代框架的扩展机制(如插件化架构、多主题支持)。
因此,抽象工厂不仅是创建型模式中的“战略工具”,更是构建灵活、可扩展系统的关键基础设施。