23种设计模式23种设计模式
首页
介绍
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 桥接模式
  • 组合模式
  • 装饰器模式
  • 外观模式
  • 享元模式
  • 代理模式
  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 访问者模式
🚀 编程指南
首页
介绍
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 桥接模式
  • 组合模式
  • 装饰器模式
  • 外观模式
  • 享元模式
  • 代理模式
  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 访问者模式
🚀 编程指南
  • 创建型模式

    • 单例模式 (Singleton)
    • 工厂方法模式 (Factory Method)
    • 抽象工厂模式 (Abstract Factory)
    • 建造者模式 (Builder)
    • 原型模式 (Prototype)

抽象工厂模式 (Abstract Factory)

📖 通俗理解

想象你要装修房子,需要买一套家具:

  • 如果选择现代风格:需要现代风格的沙发、茶几、电视柜
  • 如果选择中式风格:需要中式风格的沙发、茶几、电视柜

你不会买一个现代沙发配一个中式茶几,那样会很奇怪!

抽象工厂模式就是:提供一个创建一系列相关对象的接口,而无需指定具体类。简单说就是——一个工厂生产一套产品。

🎯 工厂方法 vs 抽象工厂

模式解决的问题例子
工厂方法生产一种产品手机工厂只生产手机
抽象工厂生产一系列产品电子产品工厂生产手机+电脑+平板

🌰 生活中的例子

  • 家具店:现代家具店卖整套现代家具,中式家具店卖整套中式家具
  • 电脑品牌:苹果生产苹果手机+电脑+耳机,华为生产华为手机+电脑+耳机
  • 汽车厂商:奔驰生产奔驰轿车+SUV+跑车,宝马生产宝马轿车+SUV+跑车

💻 Java 代码实现

场景:跨平台 UI 组件

我们要开发一个跨平台应用,需要适配 Windows 和 Mac 两个平台。每个平台都有按钮和输入框,但样式不同。

第一步:定义产品接口(产品族)

/**
 * 按钮接口
 */
public interface Button {
    void render();  // 渲染按钮
    void onClick(); // 点击事件
}

/**
 * 输入框接口
 */
public interface TextField {
    void render();          // 渲染输入框
    String getValue();      // 获取值
    void setValue(String value); // 设置值
}

第二步:实现 Windows 平台的产品

/**
 * Windows 风格按钮
 */
public class WindowsButton implements Button {
    
    @Override
    public void render() {
        System.out.println("渲染 Windows 风格的按钮 [====]");
    }
    
    @Override
    public void onClick() {
        System.out.println("Windows 按钮被点击!");
    }
}

/**
 * Windows 风格输入框
 */
public class WindowsTextField implements TextField {
    private String value = "";
    
    @Override
    public void render() {
        System.out.println("渲染 Windows 风格的输入框 |______|");
    }
    
    @Override
    public String getValue() {
        return value;
    }
    
    @Override
    public void setValue(String value) {
        this.value = value;
    }
}

第三步:实现 Mac 平台的产品

/**
 * Mac 风格按钮
 */
public class MacButton implements Button {
    
    @Override
    public void render() {
        System.out.println("渲染 Mac 风格的按钮 (====)");
    }
    
    @Override
    public void onClick() {
        System.out.println("Mac 按钮被点击!");
    }
}

/**
 * Mac 风格输入框
 */
public class MacTextField implements TextField {
    private String value = "";
    
    @Override
    public void render() {
        System.out.println("渲染 Mac 风格的输入框 |~~~~~~|");
    }
    
    @Override
    public String getValue() {
        return value;
    }
    
    @Override
    public void setValue(String value) {
        this.value = value;
    }
}

第四步:定义抽象工厂

/**
 * 抽象工厂接口
 * 定义创建一系列产品的方法
 */
public interface GUIFactory {
    Button createButton();
    TextField createTextField();
}

第五步:实现具体工厂

/**
 * Windows 工厂
 * 生产一系列 Windows 风格的组件
 */
public class WindowsFactory implements GUIFactory {
    
    @Override
    public Button createButton() {
        return new WindowsButton();
    }
    
    @Override
    public TextField createTextField() {
        return new WindowsTextField();
    }
}

/**
 * Mac 工厂
 * 生产一系列 Mac 风格的组件
 */
public class MacFactory implements GUIFactory {
    
    @Override
    public Button createButton() {
        return new MacButton();
    }
    
    @Override
    public TextField createTextField() {
        return new MacTextField();
    }
}

第六步:客户端使用

public class Application {
    private Button button;
    private TextField textField;
    
    public Application(GUIFactory factory) {
        // 使用工厂创建一系列组件
        this.button = factory.createButton();
        this.textField = factory.createTextField();
    }
    
    public void render() {
        button.render();
        textField.render();
    }
    
    public void simulate() {
        textField.setValue("Hello World");
        button.onClick();
        System.out.println("输入框的值: " + textField.getValue());
    }
    
    public static void main(String[] args) {
        // 根据操作系统选择工厂
        String os = System.getProperty("os.name").toLowerCase();
        GUIFactory factory;
        
        if (os.contains("windows")) {
            factory = new WindowsFactory();
        } else {
            factory = new MacFactory();
        }
        
        Application app = new Application(factory);
        app.render();
        app.simulate();
    }
}

Windows 下输出:

渲染 Windows 风格的按钮 [====]
渲染 Windows 风格的输入框 |______|
Windows 按钮被点击!
输入框的值: Hello World

Mac 下输出:

渲染 Mac 风格的按钮 (====)
渲染 Mac 风格的输入框 |~~~~~~|
Mac 按钮被点击!
输入框的值: Hello World

🔥 实战案例:数据库访问层

不同数据库(MySQL、Oracle)有不同的连接和命令实现。

/**
 * 数据库连接接口
 */
public interface Connection {
    void connect();
    void disconnect();
}

/**
 * 数据库命令接口
 */
public interface Command {
    void execute(String sql);
}

// ========== MySQL 产品 ==========
public class MySQLConnection implements Connection {
    @Override
    public void connect() {
        System.out.println("连接到 MySQL 数据库...");
    }
    
    @Override
    public void disconnect() {
        System.out.println("断开 MySQL 连接...");
    }
}

public class MySQLCommand implements Command {
    @Override
    public void execute(String sql) {
        System.out.println("MySQL 执行: " + sql);
    }
}

// ========== Oracle 产品 ==========
public class OracleConnection implements Connection {
    @Override
    public void connect() {
        System.out.println("连接到 Oracle 数据库...");
    }
    
    @Override
    public void disconnect() {
        System.out.println("断开 Oracle 连接...");
    }
}

public class OracleCommand implements Command {
    @Override
    public void execute(String sql) {
        System.out.println("Oracle 执行: " + sql);
    }
}

// ========== 抽象工厂 ==========
public interface DatabaseFactory {
    Connection createConnection();
    Command createCommand();
}

public class MySQLFactory implements DatabaseFactory {
    @Override
    public Connection createConnection() {
        return new MySQLConnection();
    }
    
    @Override
    public Command createCommand() {
        return new MySQLCommand();
    }
}

public class OracleFactory implements DatabaseFactory {
    @Override
    public Connection createConnection() {
        return new OracleConnection();
    }
    
    @Override
    public Command createCommand() {
        return new OracleCommand();
    }
}

使用方式:

public class DatabaseClient {
    private Connection connection;
    private Command command;
    
    public DatabaseClient(DatabaseFactory factory) {
        this.connection = factory.createConnection();
        this.command = factory.createCommand();
    }
    
    public void executeQuery(String sql) {
        connection.connect();
        command.execute(sql);
        connection.disconnect();
    }
    
    public static void main(String[] args) {
        // 使用 MySQL
        DatabaseClient mysqlClient = new DatabaseClient(new MySQLFactory());
        mysqlClient.executeQuery("SELECT * FROM users");
        
        System.out.println("-------------------");
        
        // 使用 Oracle
        DatabaseClient oracleClient = new DatabaseClient(new OracleFactory());
        oracleClient.executeQuery("SELECT * FROM users");
    }
}

📊 类图结构

┌─────────────────────────────────────────────────────────────┐
│                      AbstractFactory                         │
│  + createProductA(): AbstractProductA                        │
│  + createProductB(): AbstractProductB                        │
└─────────────────────────────────────────────────────────────┘
                              ▲
               ┌──────────────┴──────────────┐
               │                             │
    ┌──────────┴──────────┐       ┌──────────┴──────────┐
    │   ConcreteFactory1  │       │   ConcreteFactory2  │
    │ + createProductA()  │       │ + createProductA()  │
    │ + createProductB()  │       │ + createProductB()  │
    └─────────────────────┘       └─────────────────────┘
               │                             │
        创建ProductA1                  创建ProductA2
        创建ProductB1                  创建ProductB2

✅ 适用场景

  1. 系统有多个产品族:如 Windows/Mac 的 UI 组件
  2. 产品族需要一起使用:如现代风格的沙发必须配现代风格的茶几
  3. 想隐藏产品的具体实现:客户端只和工厂接口打交道

⚠️ 优缺点

优点:

  • 保证产品的一致性(同一工厂出来的产品风格统一)
  • 客户端和具体产品解耦
  • 符合开闭原则(新增产品族只需新增工厂)

缺点:

  • 新增产品类型困难(需要修改所有工厂)
  • 类的数量较多,增加系统复杂度

小结

抽象工厂模式的核心:一个工厂生产一系列相关的产品。

和工厂方法的区别:

  • 工厂方法:一个工厂生产一种产品
  • 抽象工厂:一个工厂生产一套产品

👉 下一篇:建造者模式

Prev
工厂方法模式 (Factory Method)
Next
建造者模式 (Builder)