设计模式-抽象工厂模式

抽象工厂模式

核心思想回顾:

抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象(一个产品族),而客户端代码无需指定这些对象的具体类。这使得客户端代码与具体产品的实现解耦,并且可以轻松地切换整个产品族。

场景想象:

假设你要开发一个跨平台的 UI 库,这个库需要在 Windows 和 macOS 上都能运行,并且提供各自平台原生观感的按钮和复选框。

  • 产品族1 (Windows): Windows 风格的按钮,Windows 风格的复选框。

  • 产品族2 (macOS): macOS 风格的按钮,macOS 风格的复选框。

你希望你的应用程序代码在创建这些 UI 元素时,不需要关心当前运行的是哪个操作系统,只需要告诉工厂"给我一个按钮"和"给我一个复选框",工厂就能提供与当前平台匹配的组件。

模式的参与者 (Java 实现):

  1. AbstractProduct (抽象产品):定义产品族中每种产品的接口。

    • Java: 通常是 interface。

    • 例子:interface Button, interface Checkbox。

  2. ConcreteProduct (具体产品):实现抽象产品接口,代表产品族中的具体产品。

    • Java: class 实现相应的 interface。

    • 例子:class WindowsButton implements Button, class MacOSButton implements Button, class WindowsCheckbox implements Checkbox, class MacOSCheckbox implements Checkbox。

  3. AbstractFactory (抽象工厂):声明一组用于创建抽象产品的方法。

    • Java: 通常是 interface。

    • 例子:interface GUIFactory { Button createButton(); Checkbox createCheckbox(); }。

  4. ConcreteFactory (具体工厂):实现抽象工厂接口,负责创建特定产品族中的具体产品。

    • Java: class 实现 GUIFactory 接口。

    • 例子:class WindowsFactory implements GUIFactory, class MacOSFactory implements GUIFactory。

  5. Client (客户端):仅使用 AbstractFactory 和 AbstractProduct 接口。

    • Java: 一个使用 GUIFactory 来创建 UI 组件的类。

    • 例子:class Application。

Java 示例代码:

复制代码
// 1. AbstractProduct (抽象产品接口)
interface Button {
    void paint();
}
​
interface Checkbox {
    void paint();
}
​
// 2. ConcreteProduct (具体产品 - Windows 风格)
class WindowsButton implements Button {
    @Override
    public void paint() {
        System.out.println("Rendering a Windows style button.");
    }
}
​
class WindowsCheckbox implements Checkbox {
    @Override
    public void paint() {
        System.out.println("Rendering a Windows style checkbox.");
    }
}
​
// 2. ConcreteProduct (具体产品 - macOS 风格)
class MacOSButton implements Button {
    @Override
    public void paint() {
        System.out.println("Rendering a macOS style button.");
    }
}
​
class MacOSCheckbox implements Checkbox {
    @Override
    public void paint() {
        System.out.println("Rendering a macOS style checkbox.");
    }
}
​
// 3. AbstractFactory (抽象工厂接口)
interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}
​
// 4. ConcreteFactory (具体工厂 - Windows 工厂)
class WindowsFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }
​
    @Override
    public Checkbox createCheckbox() {
        return new WindowsCheckbox();
    }
}
​
// 4. ConcreteFactory (具体工厂 - macOS 工厂)
class MacOSFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacOSButton();
    }
​
    @Override
    public Checkbox createCheckbox() {
        return new MacOSCheckbox();
    }
}
​
// 5. Client (客户端)
class Application {
    private Button button;
    private Checkbox checkbox;
    private GUIFactory factory;
​
    public Application(GUIFactory factory) {
        this.factory = factory;
    }
​
    public void createUI() {
        // 客户端不关心具体是哪个工厂,也不关心具体的产品类型
        // 它只知道从工厂获取 Button 和 Checkbox 的抽象
        this.button = factory.createButton();
        this.checkbox = factory.createCheckbox();
    }
​
    public void paintUI() {
        if (button != null && checkbox != null) {
            button.paint();
            checkbox.paint();
        } else {
            System.out.println("UI components not created yet. Call createUI() first.");
        }
    }
}
​
// 主程序,用于演示
public class AbstractFactoryDemo {
​
    // 辅助方法,根据配置或环境决定使用哪个工厂
    private static Application configureApplication() {
        GUIFactory factory;
        String osName = System.getProperty("os.name").toLowerCase();
​
        if (osName.contains("win")) {
            factory = new WindowsFactory();
            System.out.println("Configuring for Windows OS.");
        } else if (osName.contains("mac")) {
            factory = new MacOSFactory();
            System.out.println("Configuring for macOS.");
        } else {
            // 默认或不支持的操作系统,可以抛出异常或使用默认工厂
            System.out.println("OS not specifically supported, defaulting to Windows style.");
            factory = new WindowsFactory();
        }
        return new Application(factory);
    }
​
    public static void main(String[] args) {
        // 根据当前环境配置应用程序
        Application app = configureApplication();
        app.createUI();
        app.paintUI();
​
        System.out.println("\n--- Manually switching to MacOS factory for demonstration ---");
        // 强制使用 macOS 工厂进行演示
        Application macApp = new Application(new MacOSFactory());
        macApp.createUI();
        macApp.paintUI();
​
        System.out.println("\n--- Manually switching to Windows factory for demonstration ---");
        // 强制使用 Windows 工厂进行演示
        Application winApp = new Application(new WindowsFactory());
        winApp.createUI();
        winApp.paintUI();
    }
}

代码解释:

  1. Button 和 Checkbox 是抽象产品接口。

  2. WindowsButton, WindowsCheckbox, MacOSButton, MacOSCheckbox 是具体产品实现。

  3. GUIFactory 是抽象工厂接口,它声明了创建 Button 和 Checkbox 的方法。

  4. WindowsFactory 和 MacOSFactory 是具体工厂,它们分别实现了 GUIFactory,用于创建对应平台的 UI 组件。

  5. Application 是客户端。它的构造函数接收一个 GUIFactory。在 createUI() 方法中,它使用这个工厂来创建按钮和复选框,而不需要知道具体是哪个工厂或哪个产品。

  6. AbstractFactoryDemo.configureApplication() 方法模拟了根据操作系统选择合适工厂的逻辑。

  7. main 方法展示了如何使用这个模式。客户端 (Application) 的代码是通用的,只需要在初始化时传入不同的工厂实例,就能得到不同风格的 UI 组件。

优点:

  1. 隔离具体类:客户端代码与具体产品的创建逻辑解耦,只依赖于抽象接口。

  2. 易于交换产品族:改变应用程序使用的产品族非常容易,只需要更换具体工厂的实例即可。例如,从 WindowsFactory 切换到 MacOSFactory。

  3. 保证产品兼容性:因为一个具体工厂只创建属于同一个产品族的产品,所以可以保证客户端创建出来的产品是相互兼容的(例如,Windows 按钮和 Windows 复选框搭配)。

  4. 符合开闭原则(对扩展开放,对修改关闭):当需要支持一个新的产品族(比如 Linux GTK 风格)时,只需要添加新的具体产品类(GTKButton, GTKCheckbox)和新的具体工厂类(GTKFactory),而不需要修改现有的工厂接口或客户端代码。

缺点:

  1. 难以增加新的产品种类:如果要在抽象工厂接口中增加一个新的抽象产品(比如 createTextField()),那么所有的具体工厂类都需要修改以实现这个新方法。这违反了开闭原则。对于这种情况,可能需要考虑其他模式,或者对抽象工厂进行扩展。

何时使用:

  • 当你的系统需要独立于其产品的创建、组合和表示方式时。

  • 当你的系统需要配置多个产品系列中的一个时。

  • 当你希望强制用户使用同一产品系列中的对象,以保证兼容性时。

  • 当你提供一个产品库,并且只想暴露其接口,隐藏其具体实现时。

抽象工厂模式是处理复杂对象创建,特别是需要保证产品族一致性时的强大工具。

相关推荐
黎䪽圓2 小时前
【Java多线程从青铜到王者】单例设计模式(八)
java·开发语言·设计模式
小小神仙5 小时前
JSCommon系列 - 为什么前端没有 Apache Commons?
前端·javascript·设计模式
摘星编程6 小时前
原型模式深度解析:Java设计模式实战指南与克隆机制优化实践
java·设计模式·性能优化·原型模式·创建型模式·软件架构·对象克隆
胡侃有料20 小时前
【设计模式】1.简单工厂、工厂、抽象工厂模式
设计模式·抽象工厂模式
liang_jy1 天前
观察者模式
设计模式·面试
~山有木兮1 天前
C++设计模式 - 单例模式
c++·单例模式·设计模式
周某某~1 天前
四.抽象工厂模式
java·设计模式·抽象工厂模式
勤奋的知更鸟1 天前
Java编程之组合模式
java·开发语言·设计模式·组合模式
哆啦A梦的口袋呀1 天前
基于Python学习《Head First设计模式》第九章 迭代器和组合模式
python·学习·设计模式