JAVA设计模式-抽象工厂模式

抽象工厂模式是一种创建型设计模式,它为创建一组相关或相互依赖的对象提供一个接口,而无需指定它们的具体类,其核心在于管理"产品族"。该模式通过抽象层隔离了具体类的实例化过程,使得系统可以在不修改客户端代码的情况下,切换整个产品系列。

一、模式结构与核心角色

抽象工厂模式主要包含四种角色,它们共同构成了模式的骨架。

角色 职责 说明
抽象工厂 (AbstractFactory) 声明一组用于创建抽象产品对象的方法。 定义创建产品族的接口,每个方法对应一个产品等级结构。
具体工厂 (ConcreteFactory) 实现抽象工厂的接口,负责创建属于特定产品族的具体产品对象。 一个具体工厂生产的产品构成一个完整的产品族。
抽象产品 (AbstractProduct) 为每种产品声明接口。 定义一类产品的公共行为。
具体产品 (ConcreteProduct) 实现抽象产品接口,定义由具体工厂创建的具体对象。 具体工厂创建的具体实例。

其UML类图关系可简述为:客户端(Client)仅依赖于AbstractFactoryAbstractProduct接口。ConcreteFactory实现AbstractFactory,并负责实例化对应的ConcreteProductConcreteProduct则实现各自的AbstractProduct接口。

二、深入解析:产品族与产品等级结构

理解抽象工厂模式的关键在于厘清 "产品族""产品等级结构" 这两个概念。

  • 产品等级结构:指产品的抽象与具体实现之间的继承关系。例如,"按钮"是一个抽象产品,其具体实现有"Windows按钮"和"Mac按钮",它们构成了一个产品等级结构。
  • 产品族:指由同一个具体工厂创建的、分属于不同产品等级结构的一组产品。例如,由"Windows工厂"创建的"Windows按钮"和"Windows文本框"就构成了一个产品族(Windows风格族)。

抽象工厂模式就是围绕一个产品族来工作的。一个具体工厂负责生产一个产品族中的所有产品,从而保证了这些产品之间的兼容性。

三、完整代码示例:电子设备产品族

下面通过一个生产手机和电脑的电子设备产品族示例,完整展示抽象工厂模式的实现。

java 复制代码
// 1. 抽象产品:手机
interface Phone {
    void makeCall();
    void sendMessage();
}

// 2. 抽象产品:电脑
interface Computer {
    void coding();
    void playGame();
}

// 3. 具体产品:小米手机
class XiaomiPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("使用小米手机打电话。");
    }
    @Override
    public void sendMessage() {
        System.out.println("使用小米手机发短信。");
    }
}

// 4. 具体产品:小米电脑
class XiaomiComputer implements Computer {
    @Override
    public void coding() {
        System.out.println("在小米笔记本上写代码。");
    }
    @Override
    public void playGame() {
        System.out.println("用小米电脑玩游戏。");
    }
}

// 5. 具体产品:华为手机
class HuaweiPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("使用华为手机打电话。");
    }
    @Override
    public void sendMessage() {
        System.out.println("使用华为手机发短信。");
    }
}

// 6. 具体产品:华为电脑
class HuaweiComputer implements Computer {
    @Override
    public void coding() {
        System.out.println("在华为MateBook上写代码。");
    }
    @Override
    public void playGame() {
        System.out.println("用华为电脑玩游戏。");
    }
}

// 7. 抽象工厂:电子设备工厂
interface ElectronicFactory {
    Phone createPhone();
    Computer createComputer();
}

// 8. 具体工厂:小米工厂
class XiaomiFactory implements ElectronicFactory {
    @Override
    public Phone createPhone() {
        return new XiaomiPhone(); // 生产小米手机
    }
    @Override
    public Computer createComputer() {
        return new XiaomiComputer(); // 生产小米电脑
    }
}

// 9. 具体工厂:华为工厂
class HuaweiFactory implements ElectronicFactory {
    @Override
    public Phone createPhone() {
        return new HuaweiPhone(); // 生产华为手机
    }
    @Override
    public Computer createComputer() {
        return new HuaweiComputer(); // 生产华为电脑
    }
}

// 10. 客户端应用
public class Client {
    private Phone myPhone;
    private Computer myComputer;
    
    // 客户端通过抽象工厂接口构建产品族
    public Client(ElectronicFactory factory) {
        this.myPhone = factory.createPhone();
        this.myComputer = factory.createComputer();
    }
    
    public void useDevices() {
        System.out.println("开始使用设备:");
        myPhone.makeCall();
        myPhone.sendMessage();
        myComputer.coding();
        myComputer.playGame();
    }
    
    public static void main(String[] args) {
        // 模拟根据配置或用户选择决定品牌
        String brand = "Huawei"; // 可动态配置
        ElectronicFactory factory;
        
        if ("Xiaomi".equalsIgnoreCase(brand)) {
            factory = new XiaomiFactory(); // 创建小米产品族
        } else {
            factory = new HuaweiFactory(); // 创建华为产品族
        }
        
        Client customer = new Client(factory);
        customer.useDevices();
        // 当 brand = "Huawei" 时输出:
        // 开始使用设备:
        // 使用华为手机打电话。
        // 使用华为手机发短信。
        // 在华为MateBook上写代码。
        // 用华为电脑玩游戏。
    }
}

四、模式的优缺点与适用场景

优点:

  1. 保证产品兼容性:一个具体工厂创建的所有产品都属于同一产品族,它们被设计为能协同工作,避免了不匹配的问题。
  2. 符合开闭原则(对扩展开放):当需要增加一个新的产品族(如增加一个"苹果工厂")时,只需新增对应的具体工厂和具体产品类,无需修改现有抽象工厂和客户端代码。
  3. 符合单一职责原则:将产品创建代码集中到一个地方,使得代码易于维护。
  4. 符合依赖倒置原则:客户端代码只依赖于抽象接口(抽象工厂和抽象产品),不依赖于具体类。

缺点:

  1. 难以支持新种类的产品(违反开闭原则对修改关闭) :这是该模式最显著的缺点。如果需要在所有产品族中增加一个全新的产品种类(例如,在ElectronicFactory中增加createTablet()方法来生产平板电脑),就必须修改ElectronicFactory接口,这会导致所有具体工厂类都需要随之修改。
  2. 系统复杂性增加:引入了大量的接口和类,对于小型项目可能显得过于繁重。

适用场景:

场景 说明
系统需要独立于产品的创建、组合和表示 如跨平台UI库、不同数据库的访问驱动等。
系统需要配置多个产品族中的一个来使用 如选择使用一套完整的"现代风格"或"古典风格"家具。
一系列相关的产品对象需要被设计为一起使用 强调产品间的约束关系,确保客户端使用的是一套兼容的产品。
希望提供一个产品类库,只暴露接口 隐藏具体实现,向客户端提供抽象的创建接口。

五、与工厂方法模式的对比

工厂方法模式与抽象工厂模式经常被混淆,下表清晰地展示了两者的核心区别:

对比维度 工厂方法模式 (Factory Method) 抽象工厂模式 (Abstract Factory)
核心焦点 创建单个产品对象。 创建一系列相关或依赖的产品对象(产品族)。
工厂职责 一个工厂类只负责创建一种具体产品。 一个工厂类负责创建一整个产品族(包含多种产品)。
扩展方向 易于支持新的产品类型(新增产品等级结构),只需新增产品类和对应的工厂子类。 易于支持新的产品族 (新增具体工厂),但难以支持新的产品种类(需修改抽象工厂接口)。
结构复杂度 相对简单。 更为复杂。
关系 可以看作是抽象工厂模式的一种特例(只生产一种产品的抽象工厂)。抽象工厂通常使用多个工厂方法来实现。

在实际框架中,抽象工厂模式有广泛应用。例如,在Java的JDBC中,ConnectionStatement就是抽象产品,而DriverManager.getConnection()根据不同的数据库驱动返回不同的具体工厂(连接),从而创建出与特定数据库兼容的一系列对象(如Oracle的Statement或MySQL的Statement)。在MyBatis中,SqlSessionFactory也是一个典型的抽象工厂,它负责创建SqlSessionExecutor等一组相关的对象。


参考来源

相关推荐
@insist1231 小时前
信息安全工程师-密码学专题(下):构建可信网络空间的核心机制
java·大数据·密码学·软考·信息安全工程师·软件水平考试
摇滚侠1 小时前
Java 零基础全套视频教程,面向对象(高级),笔记 105-120
java·开发语言·笔记
叶落阁主2 小时前
Spring Boot 4 实战:Jackson 2.x 升级到 3.x 踩坑全记录
java·后端·架构
布吉岛的石头2 小时前
Java 中高级面试:JVM 内存模型 + GC 算法高频题总结
java·jvm·面试
故事还在继续吗2 小时前
设计模式完全指南
设计模式
2301_792674862 小时前
java学习(day32)
java
摇滚侠2 小时前
Oracle19c 导出 Oracle11g 导入,Oracle19c 导出导入,Oracle11g 导出导入
java·数据库·oracle
Stella Blog2 小时前
狂神Java基础学习笔记Day05
java·笔记·学习
曹牧2 小时前
Spring WebService 的两种主流实现方式‌
java·后端·spring