抽象工厂模式

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


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. 产品间无关联性

    • 解释:如果产品之间没有关联性或兼容性要求,不需要产品族概念。
    • 例子:创建独立的工具类对象,它们之间没有配合关系。
相关推荐
liang_jy6 小时前
工厂方法模式
android·设计模式·面试
青鱼入云7 小时前
【面试场景题】订单超时自动取消功能如何设计
面试
future_studio7 小时前
如何用 Kotlin 在 Android 手机开发一个小闹钟、计时器、秒表
android·智能手机·kotlin
Deepsleep.7 小时前
前端常见安全问题 + 防御方法 + 面试回答
前端·安全·面试
zhangguojia77 小时前
android中常见布局及其约束
android
猪哥帅过吴彦祖7 小时前
JavaScript Set 和 Map:现代 JavaScript 的数据结构双雄
前端·javascript·面试
paynnne7 小时前
Android 事件分发机制
android
郝学胜-神的一滴7 小时前
策略模式:模拟八路军的抗日策略
开发语言·c++·程序人生·设计模式·策略模式
水牛7 小时前
一行代码完成startActivityForResult
android·android jetpack