抽象工厂模式

点击阅读:设计模式系列文章


1. 抽象工厂模式的定义

抽象工厂模式(Abstract Factory Pattern) 是一种创建型设计模式,它的核心思想是: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

  1. 解决工厂方法模式只能创建单一产品的局限性。
  2. 支持创建产品家族,确保产品之间的兼容性。
  3. 客户端与具体产品类解耦,只依赖抽象接口。

核心概念:

  1. 产品族(Product Family):一组相关或相互依赖的产品对象
  2. 产品等级结构(Product Hierarchy):同一类产品的不同实现

2. 抽象工厂模式的结构

抽象工厂模式主要包含以下角色:

  • AbstractFactory(抽象工厂):定义创建一系列相关产品的接口。
  • ConcreteFactory(具体工厂):实现抽象工厂接口,创建特定产品族的所有产品。
  • AbstractProduct(抽象产品):定义产品对象的接口。
  • ConcreteProduct(具体产品):实现抽象产品接口,属于特定产品族。
txt 复制代码
Client
   |
AbstractFactory (抽象)
   |
ConcreteFactoryA --> ProductA1, ProductA2, ProductA3
ConcreteFactoryB --> ProductB1, ProductB2, ProductB3

特点:

  • 每个具体工厂负责创建一个完整的产品族。
  • 产品族内的产品相互配合,保证兼容性。
  • 客户端只依赖抽象接口,不关心具体实现。

2.1 AbstractFactory 抽象工厂

java 复制代码
public interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
    Menu createMenu();
}

2.2 ConcreteFactory 具体工厂

java 复制代码
public class WinFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WinButton();
    }
    
    @Override
    public Checkbox createCheckbox() {
        return new WinCheckbox();
    }
    
    @Override
    public Menu createMenu() {
        return new WinMenu();
    }
}

public class MacFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacButton();
    }
    
    @Override
    public Checkbox createCheckbox() {
        return new MacCheckbox();
    }
    
    @Override
    public Menu createMenu() {
        return new MacMenu();
    }
}

2.3 AbstractProduct 抽象产品

java 复制代码
public interface Button {
    void render();
    void onClick();
}

public interface Checkbox {
    void render();
    void toggle();
}

public interface Menu {
    void render();
    void show();
}

2.4 ConcreteProduct 具体产品

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

public class MacButton implements Button {
    @Override
    public void render() {
        System.out.println("渲染Mac风格按钮");
    }
    
    @Override
    public void onClick() {
        System.out.println("Mac按钮点击事件处理");
    }
}

2.5 Client 客户端

java 复制代码
public class Application {
    private Button button;
    private Checkbox checkbox;
    private Menu menu;
    
    public Application(GUIFactory factory) {
        this.button = factory.createButton();
        this.checkbox = factory.createCheckbox();
        this.menu = factory.createMenu();
    }
    
    public void renderUI() {
        button.render();
        checkbox.render();
        menu.render();
    }
    
    public static void main(String[] args) {
        GUIFactory factory;
        String osName = System.getProperty("os.name").toLowerCase();
        
        if (osName.contains("win")) {
            factory = new WinFactory();
        } else if (osName.contains("mac")) {
            factory = new MacFactory();
        } else {
            throw new UnsupportedOperationException("不支持的操作系统");
        }
        
        Application app = new Application(factory);
        app.renderUI();
    }
}

3. 抽象工厂模式的优缺点

优点:

  1. 产品族一致性:确保创建的对象属于同一产品族,保证兼容性。
  2. 开闭原则:新增产品族无需修改已有代码,只需添加新的具体工厂。
  3. 客户端解耦:客户端只依赖抽象接口,不关心具体实现。
  4. 切换便捷:可以轻松切换整个产品家族。

缺点:

  1. 扩展产品等级困难:新增产品类型需要修改所有工厂接口和实现。
  2. 类数量膨胀:产品族数量×产品等级数量=类的总数量。
  3. 复杂性高:多重抽象增加理解和维护难度。
  4. 违反开闭原则:新增产品等级时需要修改抽象工厂接口。

4. 抽象工厂模式的设计思想

  • 产品族一致性:确保同一产品族内的产品相互兼容。

  • 接口隔离:客户端只依赖抽象工厂和抽象产品接口。

  • 开闭原则:对扩展开放(新增产品族),对修改关闭(已有代码)。

  • 依赖倒置:高层模块不依赖低层模块,都依赖抽象。

  • 单一职责:每个具体工厂只负责创建一个产品族。

5. 一些问题

Q1: 抽象工厂模式与工厂方法模式的区别是什么?

A1:

  • 工厂方法模式:一个工厂只创建一种产品,关注单个产品的创建
  • 抽象工厂模式:一个工厂创建一族相关产品,关注产品家族的创建
  • 核心区别:工厂方法强调"单一产品的多态创建",抽象工厂强调"产品族的一致性创建"
java 复制代码
// 工厂方法:每个工厂只创建一种产品
ButtonFactory -> Button
CheckboxFactory -> Checkbox

// 抽象工厂:每个工厂创建一族产品
WinFactory -> WinButton, WinCheckbox, WinMenu
MacFactory -> MacButton, MacCheckbox, MacMenu

Q2: 抽象工厂模式在什么场景下不适用?

  1. 单一产品创建

    • 解释:如果只需要创建单个产品,使用抽象工厂会增加不必要的复杂性。
    • 例子:只需要创建按钮组件,不需要整套UI组件时,用简单工厂或工厂方法更合适。
  2. 产品族不稳定

    • 解释:如果产品类型经常变化,抽象工厂的接口需要频繁修改。
    • 例子:UI组件库经常新增或删除组件类型,会导致所有工厂接口都需要修改。
  3. 性能敏感场景

    • 解释:多层抽象和工厂创建会带来额外的性能开销。
    • 例子:游戏引擎中的高频对象创建,直接new对象可能比工厂创建更高效。
  4. 产品间无关联性

    • 解释:如果产品之间没有关联性或兼容性要求,不需要产品族概念。
    • 例子:创建独立的工具类对象,它们之间没有配合关系。
相关推荐
传奇开心果1 小时前
【Compose Multiplatform跨端声明式UI实用技术】第9课:跨平台 ViewModel 与状态架构
android·kotlin
用户69371750013842 小时前
当你向领导申请 AI 编程工具预算时,如果领导追问“能提效多少,有量化数据吗”,你该怎么回答?
android·后端·ios
hunterandroid3 小时前
WorkManager 后台任务调度实战:从一次性任务到周期执行
android
事圆则缓3 小时前
Android 屏幕适配的前世今生
android
Rain的Java大神之路3 小时前
MySQL 被高并发打爆?从定位到分库分表逐层拆解(含秒杀库存实战)
java·后端·面试
andyweike3 小时前
kotlin dsl library工程怎么配置
android·开发语言·kotlin
啵啵啵鱼3 小时前
九、JDBC 操作 MySQL 数据库
android·数据库·mysql
用户69371750013844 小时前
当我说 Claude 搭配 GLM-5.3-Flash 太好用了,同事却提醒我:你可能正在失去对代码的掌控
android·后端·ios
张小姐的猫4 小时前
【MySQL】数据类型
android·linux·数据库·c++·mysql·adb·php
2501_916008894 小时前
马甲包过审卡在哪?Ipa Guard 能做的和做不到的
android·小程序·https·uni-app·iphone·webview