23种设计模式一抽象工厂模式‌

一、概念解析

1.1 什么是抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序不需要知道具体工厂的实现,只需要通过抽象工厂接口来创建一系列相关或相互依赖的对象。

1.2 核心思想

抽象工厂模式的核心思想是:将对象的创建逻辑封装在工厂类中,客户端通过工厂接口来创建对象,而不需要关心具体的实现细节。这样可以降低客户端与具体产品类之间的耦合度。

1.3 生活类比

举个生活中的例子:假设你要装修房子,需要购买家具。你可以选择:

  • 欧式风格家具店:购买欧式的沙发、餐桌、床等
  • 中式风格家具店:购买中式的沙发、餐桌、床等

在这个场景中:

  • 家具店就是抽象工厂
  • 欧式家具店和中式家具店是具体工厂
  • 沙发、餐桌、床是抽象产品
  • 欧式沙发、中式沙发等是具体产品

你只需要告诉家具店(工厂)你需要什么类型的家具,而不需要关心家具的具体制作过程。

1.4 解决的问题

抽象工厂模式主要解决以下问题:

  1. 产品族的管理:当需要创建一组相关的产品对象时,确保这些产品属于同一个系列
  2. 解耦客户端与具体实现:客户端不需要知道具体产品的创建细节
  3. 方便扩展新的产品系列:新增产品族时,只需添加新的具体工厂,无需修改客户端代码

二、UML类图

2.1 标准UML类图

<<interface>>
AbstractFactory
+createProductA() : AbstractProductA
+createProductB() : AbstractProductB
ConcreteFactory1
+createProductA() : ConcreteProductA1
+createProductB() : ConcreteProductB1
ConcreteFactory2
+createProductA() : ConcreteProductA2
+createProductB() : ConcreteProductB2
<<interface>>
AbstractProductA
+operation() : void
<<interface>>
AbstractProductB
+operation() : void
ConcreteProductA1
+operation() : void
ConcreteProductB1
+operation() : void
ConcreteProductA2
+operation() : void
ConcreteProductB2
+operation() : void
Client
-factory AbstractFactory
-productA AbstractProductA
-productB AbstractProductB
+run() : void

2.2 角色说明

角色 说明
AbstractFactory 抽象工厂接口,声明创建抽象产品的方法
ConcreteFactory 具体工厂实现类,实现创建具体产品的逻辑
AbstractProduct 抽象产品接口,定义产品的公共方法
ConcreteProduct 具体产品实现类,实现具体的产品功能
Client 客户端,通过抽象工厂接口使用产品

三、代码实现

下面以跨平台UI组件为例,实现一个完整的抽象工厂模式示例。

3.1 抽象产品接口

java 复制代码
// 抽象产品:按钮
public interface Button {
    void render();
    void onClick();
}

// 抽象产品:文本框
public interface TextField {
    void render();
    void onInput();
}

// 抽象产品:复选框
public interface Checkbox {
    void render();
    void onCheck();
}

3.2 具体产品实现类

java 复制代码
// Windows风格按钮
public class WindowsButton implements Button {
    @Override
    public void render() {
        System.out.println("渲染Windows风格按钮");
    }
    
    @Override
    public void onClick() {
        System.out.println("Windows按钮被点击");
    }
}

// Windows风格文本框
public class WindowsTextField implements TextField {
    @Override
    public void render() {
        System.out.println("渲染Windows风格文本框");
    }
    
    @Override
    public void onInput() {
        System.out.println("Windows文本框输入内容");
    }
}

// Windows风格复选框
public class WindowsCheckbox implements Checkbox {
    @Override
    public void render() {
        System.out.println("渲染Windows风格复选框");
    }
    
    @Override
    public void onCheck() {
        System.out.println("Windows复选框被选中");
    }
}

// MacOS风格按钮
public class MacOSButton implements Button {
    @Override
    public void render() {
        System.out.println("渲染MacOS风格按钮");
    }
    
    @Override
    public void onClick() {
        System.out.println("MacOS按钮被点击");
    }
}

// MacOS风格文本框
public class MacOSTextField implements TextField {
    @Override
    public void render() {
        System.out.println("渲染MacOS风格文本框");
    }
    
    @Override
    public onInput() {
        System.out.println("MacOS文本框输入内容");
    }
}

// MacOS风格复选框
public class MacOSCheckbox implements Checkbox {
    @Override
    public void render() {
        System.out.println("渲染MacOS风格复选框");
    }
    
    @Override
    public void onCheck() {
        System.out.println("MacOS复选框被选中");
    }
}

3.3 抽象工厂接口

java 复制代码
// 抽象工厂:UI组件工厂
public interface GUIFactory {
    Button createButton();
    TextField createTextField();
    Checkbox createCheckbox();
}

3.4 具体工厂实现类

java 复制代码
// Windows风格工厂
public class WindowsFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }
    
    @Override
    public TextField createTextField() {
        return new WindowsTextField();
    }
    
    @Override
    public Checkbox createCheckbox() {
        return new WindowsCheckbox();
    }
}

// MacOS风格工厂
public class MacOSFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacOSButton();
    }
    
    @Override
    public TextField createTextField() {
        return new MacOSTextField();
    }
    
    @Override
    public Checkbox createCheckbox() {
        return new MacOSCheckbox();
    }
}

3.5 客户端调用代码

java 复制代码
// 客户端应用
public class Application {
    private Button button;
    private TextField textField;
    private Checkbox checkbox;
    
    public Application(GUIFactory factory) {
        button = factory.createButton();
        textField = factory.createTextField();
        checkbox = factory.createCheckbox();
    }
    
    public void render() {
        button.render();
        textField.render();
        checkbox.render();
    }
    
    public void interact() {
        button.onClick();
        textField.onInput();
        checkbox.onCheck();
    }
}

// 配置类:根据配置选择工厂
public class ApplicationConfigurator {
    public static GUIFactory createFactory(String osType) {
        if ("windows".equalsIgnoreCase(osType)) {
            return new WindowsFactory();
        } else if ("macos".equalsIgnoreCase(osType)) {
            return new MacOSFactory();
        } else {
            throw new IllegalArgumentException("不支持的操作系统类型: " + osType);
        }
    }
}

// 测试客户端
public class ClientDemo {
    public static void main(String[] args) {
        // 场景1:Windows平台
        System.out.println("=== Windows平台应用 ===");
        GUIFactory windowsFactory = ApplicationConfigurator.createFactory("windows");
        Application windowsApp = new Application(windowsFactory);
        windowsApp.render();
        windowsApp.interact();
        
        System.out.println();
        
        // 场景2:MacOS平台
        System.out.println("=== MacOS平台应用 ===");
        GUIFactory macosFactory = ApplicationConfigurator.createFactory("macos");
        Application macosApp = new Application(macosFactory);
        macosApp.render();
        macosApp.interact();
    }
}

3.6 运行结果

复制代码
=== Windows平台应用 ===
渲染Windows风格按钮
渲染Windows风格文本框
渲染Windows风格复选框
Windows按钮被点击
Windows文本框输入内容
Windows复选框被选中

=== MacOS平台应用 ===
渲染MacOS风格按钮
渲染MacOS风格文本框
渲染MacOS风格复选框
MacOS按钮被点击
MacOS文本框输入内容
MacOS复选框被选中

四、应用场景

抽象工厂模式适用于以下场景:

4.1 跨平台UI组件库

  • 场景:开发需要在Windows、MacOS、Linux等多个平台运行的桌面应用
  • 优势:确保同一平台的所有UI组件风格一致
  • 示例:Java Swing、Qt等UI框架

4.2 数据库访问层

  • 场景:应用需要支持多种数据库(MySQL、Oracle、PostgreSQL等)

  • 优势:统一管理不同数据库的连接、命令、参数等对象

  • 示例

    java 复制代码
    DatabaseFactory factory = new MySQLFactory();
    Connection conn = factory.createConnection();
    Command cmd = factory.createCommand();

4.3 游戏开发中的不同风格

  • 场景:游戏需要支持多种视觉风格(古典、科幻、奇幻等)
  • 优势:确保同一风格下的角色、道具、场景保持一致
  • 示例:创建角色工厂、武器工厂、地图工厂

4.4 日志系统实现

  • 场景:需要支持多种日志输出方式(文件日志、数据库日志、远程日志等)
  • 优势:统一管理日志格式、存储位置、输出策略
  • 示例:Log4j、Logback等日志框架的设计

4.5 支付系统集成

  • 场景:电商系统需要集成多种支付渠道(支付宝、微信支付、银联等)
  • 优势:统一管理不同支付方式的请求、响应、回调处理
  • 示例:创建支付工厂、订单工厂、退款工厂

五、优缺点分析

5.1 优点

优点 说明
解耦 客户端与具体产品类解耦,符合开闭原则
产品族一致性 确保同一产品族的产品一起使用,避免混用
扩展性强 新增产品族时,只需添加新的具体工厂
代码复用 相同产品族的创建逻辑集中在工厂中,便于维护
符合单一职责 每个具体工厂只负责创建一个产品族

5.2 缺点

缺点 说明
复杂性增加 类的数量增加,系统复杂度提高
扩展困难 新增产品种类时需要修改所有工厂类
过度抽象 简单场景使用会带来不必要的复杂性
难以应对产品族变动 产品族结构变化时需要大量修改代码

5.3 使用建议

  • 适合使用:产品族稳定,需要经常新增产品族时
  • 不适合使用:产品族结构经常变化,或者只有单一产品时

六、与工厂方法模式的区别

抽象工厂模式和工厂方法模式都是创建型模式,但两者有明显区别:

6.1 对比表格

对比维度 工厂方法模式 抽象工厂模式
创建对象数量 创建一种产品 创建一组相关产品
抽象层次 一层抽象(工厂) 两层抽象(产品族+产品)
工厂职责 每个工厂创建一种产品 每个工厂创建一个产品族
扩展方向 易于新增产品种类 易于新增产品族
复杂度 相对简单 相对复杂

6.2 代码对比

工厂方法模式

java 复制代码
// 只有一种产品
interface Product { void operation(); }

class ConcreteProduct implements Product {
    public void operation() { /* ... */ }
}

// 工厂只创建一种产品
interface Factory {
    Product createProduct();
}

抽象工厂模式

java 复制代码
// 多种产品组成产品族
interface ProductA { void operationA(); }
interface ProductB { void operationB(); }

class ConcreteProductA implements ProductA { /* ... */ }
class ConcreteProductB implements ProductB { /* ... */ }

// 工厂创建整个产品族
interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

6.3 选择建议

  • 选择工厂方法模式:只需要创建一种产品对象时
  • 选择抽象工厂模式:需要创建多个相关或依赖的产品对象时

七、最佳实践

7.1 设计建议

1. 合理划分产品族

java 复制代码
// 好的设计:按功能划分
interface VehicleFactory {
    Car createCar();
    Bike createBike();
}

// 不好的设计:混合不同概念
interface MixedFactory {
    Car createCar();
    Pizza createPizza();  // 不相关的产品
}

2. 使用配置管理工厂选择

java 复制代码
public class FactoryProvider {
    private static final Map<String, GUIFactory> factories = new HashMap<>();
    
    static {
        factories.put("windows", new WindowsFactory());
        factories.put("macos", new MacOSFactory());
    }
    
    public static GUIFactory getFactory(String type) {
        GUIFactory factory = factories.get(type.toLowerCase());
        if (factory == null) {
            throw new IllegalArgumentException("未知的工厂类型: " + type);
        }
        return factory;
    }
}

3. 结合依赖注入使用

java 复制代码
@Service
public class OrderService {
    private final PaymentFactory paymentFactory;
    
    @Autowired
    public OrderService(PaymentFactory paymentFactory) {
        this.paymentFactory = paymentFactory;
    }
    
    public void processOrder(Order order) {
        Payment payment = paymentFactory.createPayment();
        payment.pay(order.getAmount());
    }
}

7.2 注意事项

  1. 避免过度设计:简单场景不要使用抽象工厂模式
  2. 保持接口稳定:抽象工厂接口一旦确定,尽量避免修改
  3. 合理控制产品族数量:产品族过多会增加系统复杂度
  4. 考虑使用反射:可以使用反射动态创建工厂,减少硬编码
  5. 文档化产品族:清晰说明每个产品族包含哪些产品

7.3 反射优化示例

java 复制代码
public class ReflectionFactoryProvider {
    public static GUIFactory createFactory(String className) {
        try {
            Class<?> clazz = Class.forName(className);
            return (GUIFactory) clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("创建工厂失败: " + className, e);
        }
    }
}

// 使用示例
GUIFactory factory = ReflectionFactoryProvider.createFactory(
    "com.example.WindowsFactory"
);

总结

抽象工厂模式是一个强大的创建型设计模式,它通过抽象工厂产品族的概念,为客户端提供了一种创建一系列相关对象的统一方式。

核心要点回顾

  1. 产品族概念:抽象工厂模式的核心是产品族,确保同一族的产品风格一致
  2. 两层抽象:抽象工厂接口和抽象产品接口构成两层抽象层次
  3. 开闭原则:新增产品族时无需修改客户端代码
  4. 适用场景:适合产品族稳定,需要支持多个产品族的场景
  5. 谨慎使用:简单场景使用会增加不必要的复杂性

与工厂方法模式的区别 :抽象工厂模式创建的是产品族 ,而工厂方法模式创建的是单一产品

在实际项目中,合理使用抽象工厂模式可以大大提高代码的可维护性和扩展性,但也要避免过度设计,根据实际需求选择合适的设计模式。

相关推荐
短剑重铸之日3 小时前
《设计模式》第二篇:单例模式
java·单例模式·设计模式·懒汉式·恶汉式
短剑重铸之日5 小时前
《设计模式》第一篇:初识
java·后端·设计模式
酉鬼女又兒1 天前
java三个工厂设计模式
java·开发语言·设计模式
Engineer邓祥浩1 天前
设计模式学习(26) 总结(杂想)
java·学习·设计模式
奔跑的web.1 天前
前端使用7种设计模式的核心原则
前端·javascript·设计模式·typescript·vue
钦拆大仁2 天前
Java设计模式-单例模式
java·单例模式·设计模式
娟宝宝萌萌哒2 天前
智能体设计模式重点
人工智能·设计模式
Andy&lin2 天前
【医疗】智慧病房APP原型模板
设计模式·产品运营·人机交互·交互·健康医疗
Engineer邓祥浩2 天前
设计模式学习(22) 23-20 解释器模式
学习·设计模式·解释器模式