【抽象工厂模式】

39 阅读4分钟

定义

  • 抽象工厂模式是一种创建型设计模式
  • 抽象工厂模式可以用于创建一组相关的对象,而无需指定具体的类

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

  1. 抽象工厂(Abstract Factory) :声明了一组用于创建不同产品对象的方法,这些方法的返回类型通常为抽象产品类型。
  2. 具体工厂(Concrete Factory) :实现抽象工厂中的抽象方法,负责创建具体的产品对象组合。
  3. 抽象产品(Abstract Product) :定义产品的公共接口,所有具体产品类都实现这个接口。
  4. 具体产品(Concrete Product) :实现抽象产品接口的具体类,代表不同类型的产品对象

业务

类图

classDiagram
direction LR
    class Button {
    <<interface>>
        +paint()
    }
    class WindowsButton {
        +paint()
    }
    class MacButton {
        +paint()
    }
    class LinuxButton {
        +paint()
    }
    class TextBox {
    <<interface>>
        +display()
    }
    class WindowsTextBox {
        +display()
    }
    class MacTextBox {
        +display()
    }
    class LinuxTextBox {
        +display()
    }
    class Menu {
    <<interface>>
        +show()
    }
    class WindowsMenu {
        +show()
    }
    class MacMenu {
        +show()
    }
    class LinuxMenu {
        +show()
    }
    class GUIFactory {
    <<interface>>
        +createButton(): Button
        +createTextBox(): TextBox
        +createMenu(): Menu
    }
    class WindowsFactory {
        +createButton(): Button
        +createTextBox(): TextBox
        +createMenu(): Menu
    }
    class MacFactory {
        +createButton(): Button
        +createTextBox(): TextBox
        +createMenu(): Menu
    }
    class LinuxFactory {
        +createButton(): Button
        +createTextBox(): TextBox
        +createMenu(): Menu
    }
    Button <|-- WindowsButton
    Button <|-- MacButton
    Button <|-- LinuxButton
    TextBox <|-- WindowsTextBox
    TextBox <|-- MacTextBox
    TextBox <|-- LinuxTextBox
    Menu <|-- WindowsMenu
    Menu <|-- MacMenu
    Menu <|-- LinuxMenu
    WindowsButton <-- WindowsFactory
    WindowsTextBox <-- WindowsFactory
    WindowsMenu <-- WindowsFactory
    
    LinuxButton <-- LinuxFactory
    LinuxTextBox <-- LinuxFactory
    LinuxMenu <-- LinuxFactory
    
    MacButton <-- MacFactory
    MacTextBox <-- MacFactory
    MacMenu <-- MacFactory
    
    
    WindowsFactory --> GUIFactory
    MacFactory --> GUIFactory
    LinuxFactory --> GUIFactory

代码

假设我们正在开发一个图形用户界面(GUI)库,需要支持不同的操作系统,如 Windows、Mac 和 Linux。每个操作系统都有自己的特定风格的按钮、文本框和菜单。我们可以使用抽象工厂模式来创建这些不同操作系统的 GUI 组件。 首先,定义抽象产品接口:

interface Button {
    void paint();
}

interface TextBox {
    void display();
}

interface Menu {
    void show();
}

然后,实现具体产品类:

Windows 风格的组件:

class WindowsButton implements Button {
    @Override
    public void paint() {
        System.out.println("绘制 Windows 风格的按钮");
    }
}

class WindowsTextBox implements TextBox {
    @Override
    public void display() {
        System.out.println("显示 Windows 风格的文本框");
    }
}

class WindowsMenu implements Menu {
    @Override
    public void show() {
        System.out.println("展示 Windows 风格的菜单");
    }
}

Mac 风格的组件:

class MacButton implements Button {
    @Override
    public void paint() {
        System.out.println("绘制 Mac 风格的按钮");
    }
}

class MacTextBox implements TextBox {
    @Override
    public void display() {
        System.out.println("显示 Mac 风格的文本框");
    }
}

class MacMenu implements Menu {
    @Override
    public void show() {
        System.out.println("展示 Mac 风格的菜单");
    }
}

Linux 风格的组件:

class LinuxButton implements Button {
    @Override
    public void paint() {
        System.out.println("绘制 Linux 风格的按钮");
    }
}

class LinuxTextBox implements TextBox {
    @Override
    public void display() {
        System.out.println("显示 Linux 风格的文本框");
    }
}

class LinuxMenu implements Menu {
    @Override
    public void show() {
        System.out.println("展示 Linux 风格的菜单");
    }
}

接下来,定义抽象工厂接口:

interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
    Menu createMenu();
}

然后,实现具体工厂类:

Windows 工厂:

class WindowsFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public TextBox createTextBox() {
        return new WindowsTextBox();
    }

    @Override
    public Menu createMenu() {
        return new WindowsMenu();
    }
}

Mac 工厂:

class MacFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacButton();
    }

    @Override
    public TextBox createTextBox() {
        return new MacTextBox();
    }

    @Override
    public Menu createMenu() {
        return new MacMenu();
    }
}

Linux 工厂:

class LinuxFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new LinuxButton();
    }

    @Override
    public TextBox createTextBox() {
        return new LinuxTextBox();
    }

    @Override
    public Menu createMenu() {
        return new LinuxMenu();
    }
}

在业务代码中,可以使用抽象工厂来创建不同操作系统的 GUI 组件:

public class Main {
    public static void main(String[] args) {
        GUIFactory factory;

        // 创建 Windows 风格的 GUI 组件
        factory = new WindowsFactory();
        Button button = factory.createButton();
        TextBox textBox = factory.createTextBox();
        Menu menu = factory.createMenu();
        button.paint();
        textBox.display();
        menu.show();

        // 创建 Mac 风格的 GUI 组件
        factory = new MacFactory();
        button = factory.createButton();
        textBox = factory.createTextBox();
        menu = factory.createMenu();
        button.paint();
        textBox.display();
        menu.show();

        // 创建 Linux 风格的 GUI 组件
        factory = new LinuxFactory();
        button = factory.createButton();
        textBox = factory.createTextBox();
        menu = factory.createMenu();
        button.paint();
        textBox.display();
        menu.show();
    }
}

优点

  1. 易于切换产品系列。如果需要切换到不同的操作系统风格的 GUI 组件,只需要更换具体工厂即可,客户端代码无需修改。
  2. 代码结构更加清晰。将不同操作系统的 GUI 组件的创建逻辑封装在不同的工厂类中,使得代码的职责更加明确。

缺点

  1. 难以支持新的产品种类。如果需要添加一种新的 GUI 组件,比如进度条,需要修改所有的具体工厂类和抽象工厂接口,这可能会导致较大的修改成本。

在框架中的使用

java

java swing图形用户界面库,类似上述java业务

spring

无 如 PlatformTransactionManager、DataSourceTransactionManager 只生成一个对象,属于工厂方法模式

mybatis

总结

抽象工厂 + 每个工厂生产多种产品

总的来说,抽象工厂模式适用于创建一组相关的对象,且这些对象的创建逻辑比较复杂,需要根据不同的情况进行切换的场景。

设计模式对比1对比2
简单工厂模式没有抽象工厂,创建时直接生成的对象指定具体类一个工厂创建一种对象
工厂方法模式引入抽象工厂,创建时直接生成的对象指定抽象类(接口)一个工厂创建一种对象
抽象工厂模式引入抽象工厂,创建时直接生成的对象指定抽象类(接口)一个工厂创建多种对象