自学教程 学编程从这里开始

抽象工厂模式

《抽象工厂模式》|设计模式系列第04篇

系列:创建型模式 · 抽象工厂模式(Abstract Factory Pattern)
关键词:产品族、产品等级、抽象工厂、一套相关产品、工厂方法升级版

一、什么是抽象工厂模式

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖产品的接口,而无需指定它们具体的类。

属于创建型设计模式。

区分工厂方法 vs 抽象工厂

  • 工厂方法:一个工厂只生产一种产品(单一产品)
  • 抽象工厂:一个工厂可以生产一组配套产品(产品族)

两个核心概念:

  1. 产品族:同一个工厂产出的一组配套产品。例如:小米工厂生产小米手机、小米耳机;华为工厂生产华为手机、华为耳机。
  2. 产品等级:同类产品的不同实现。手机是一个产品等级,耳机是另一个产品等级。

核心意图

保证客户端使用同一产品族的一套产品;隔离具体产品的创建,客户端只依赖抽象接口。新增产品族很方便,但新增产品等级非常麻烦。

适用场景

  1. 系统需要成套创建一组相关联的产品,保证配套使用
  2. 产品有多个系列,系统只需要使用其中某一个系列
  3. 希望客户端只使用抽象接口,屏蔽具体产品实现类

⚠️ 缺点预警:当产品族需要新增一类产品(新增产品等级),抽象工厂和所有具体工厂都要修改,违反开闭原则。

二、UML结构图

角色划分:

  1. AbstractFactory(抽象工厂):声明一组创建不同产品的方法
  2. ConcreteFactory(具体工厂):实现抽象工厂,生产对应产品族的全部产品
  3. AbstractProduct(抽象产品):每种产品的公共接口(多个抽象产品)
  4. ConcreteProduct(具体产品):抽象产品的具体实现,属于某个产品族

三、Java 完整示例

场景:电子产品工厂,可以生产手机 Phone 和耳机 Headphone。
产品族:小米产品族、华为产品族。
产品等级:手机、耳机。

1. 抽象产品

// 抽象产品:手机
public interface Phone {
    void call();
}

// 抽象产品:耳机
public interface Headphone {
    void listen();
}

2. 具体产品

// 小米手机
public class MiPhone implements Phone {
    @Override
    public void call() {
        System.out.println("小米手机拨打电话");
    }
}

// 小米耳机
public class MiHeadphone implements Headphone {
    @Override
    public void listen() {
        System.out.println("小米耳机播放音频");
    }
}

// 华为手机
public class HuaweiPhone implements Phone {
    @Override
    public void call() {
        System.out.println("华为手机拨打电话");
    }
}

// 华为耳机
public class HuaweiHeadphone implements Headphone {
    @Override
    public void listen() {
        System.out.println("华为耳机播放音频");
    }
}

3. 抽象工厂

// 抽象工厂:电子产品工厂,可以生产手机+耳机一组产品
public interface ElectronicFactory {
    Phone createPhone();
    Headphone createHeadphone();
}

4. 具体工厂

// 小米工厂:小米产品族
public class MiFactory implements ElectronicFactory {
    @Override
    public Phone createPhone() {
        return new MiPhone();
    }

    @Override
    public Headphone createHeadphone() {
        return new MiHeadphone();
    }
}

// 华为工厂:华为产品族
public class HuaweiFactory implements ElectronicFactory {
    @Override
    public Phone createPhone() {
        return new HuaweiPhone();
    }

    @Override
    public Headphone createHeadphone() {
        return new HuaweiHeadphone();
    }
}

5. 客户端调用

public class Client {
    public static void main(String[] args) {
        // 切换工厂即可切换整套产品族
        ElectronicFactory factory = new MiFactory();
        Phone phone = factory.createPhone();
        Headphone headphone = factory.createHeadphone();
        phone.call();
        headphone.listen();

        System.out.println("=====切换华为产品族=====");
        factory = new HuaweiFactory();
        phone = factory.createPhone();
        headphone = factory.createHeadphone();
        phone.call();
        headphone.listen();
    }
}

客户端只依赖抽象 ElectronicFactory、Phone、Headphone,所有具体类隔离。
想要切换整套产品,只需要更换一行工厂实例代码。

四、优缺点总结

✅ 优点

  1. 保证同一产品族的产品配套使用
  2. 新增产品族简单,符合开闭原则
  3. 客户端与具体产品解耦,面向抽象编程

❌ 缺点

  1. 新增产品等级困难:例如要新增手表 Watch,抽象工厂接口要增加方法,所有工厂都要修改,破坏开闭原则
  2. 类数量多,结构复杂

五、工厂方法 vs 抽象工厂对比

模式生产能力扩展特点
工厂方法模式一个工厂只生产一种产品新增产品简单,类爆炸
抽象工厂模式一个工厂生产一组配套产品新增产品族简单;新增产品等级困难

六、框架源码应用

  • JDK java.sql:Connection、Statement 就是产品族;不同数据库驱动就是具体工厂
  • Spring BeanFactory 部分子接口,类似抽象工厂思想

七、小结

抽象工厂核心:工厂可以生产一整套相关产品,用来约束产品族。
适合产品等级固定,产品族需要频繁扩展的场景。如果产品等级经常变动,不要使用抽象工厂。

标签:

0 条笔记