抽象工厂模式

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


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

    • 解释:如果产品之间没有关联性或兼容性要求,不需要产品族概念。
    • 例子:创建独立的工具类对象,它们之间没有配合关系。
相关推荐
峰哥的Android进阶之路4 分钟前
handler机制原理面试总结
android·面试
雨白6 分钟前
让代码更清晰:Android 中的 MVC、MVP 与 MVVM
android·mvc·mvvm
魑魅魍魉都是鬼16 分钟前
不练不熟,不写就忘 之 compose 之 动画之 animateSizeAsState动画练习
android·compose
guangzan19 分钟前
TypeScript 中的策略模式
设计模式
一只柠檬新1 小时前
当AI开始读源码,调Bug这件事彻底变了
android·人工智能·ai编程
正经教主1 小时前
【App开发】手机投屏的几种方式(含QtScrcpy)- Android 开发新人指南
android·智能手机
晴殇i2 小时前
前端架构中的中间层设计:构建稳健可维护的组件体系
前端·面试·代码规范
学历真的很重要2 小时前
LangChain V1.0 Messages 详细指南
开发语言·后端·语言模型·面试·langchain·职场发展·langgraph
乐悠小码2 小时前
Java设计模式精讲---04原型模式
java·设计模式·原型模式
多则惑少则明2 小时前
高频面试八股文用法篇(十五)如何高效操作字符串?
面试·职场和发展