设计模式 - 抽象工厂模式:统一不同代码风格下的代码级别

在这里插入图片描述

引言

在 GoF 的《设计模式》中,工厂模式分为三类:简单工厂、工厂方法、抽象工厂。实际工作中,工厂方法和抽象工厂最常用。抽象工厂模式的难点,不是代码实现,而是如何找到“正确的抽象”——它必须既简单又底层,才能真正发挥作用。今天,我们直奔主题,掌握抽象工厂模式的精髓。


模式定义与底层逻辑

定义:提供一个创建相关或相互依赖对象族的接口,而无需指定它们的具体类。

  • 对使用者说:只关心一组产品(如家具系列),不在意品牌和型号。
  • 对创建者说:需分析共性功能,找到正确的抽象产品接口,再交由具体工厂实现。

核心思想:提炼共性抽象,隐藏具体实现


通用 UML 与角色说明

┌──────────────────┐      ┌──────────────────┐
│ AbstractFactory │─────▶│ AbstractProductA │
│  + createA()    │      └──────────────────┘
│  + createB()    │─┐
└──────────────────┘ │      ┌──────────────────┐
                     └────▶│ AbstractProductB │
                            └──────────────────┘

┌──────────────────┐      ┌──────────────────┐
│ ConcreteFactory1 │─────▶│ ConcreteProductA1│
│  + createA()    │      └──────────────────┘
│  + createB()    │─┐
└──────────────────┘ │      ┌──────────────────┐
                     └────▶│ ConcreteProductB1│
                            └──────────────────┘
  • AbstractFactory:抽象工厂,声明创建一组产品的方法。
  • ConcreteFactory:具体工厂,实现 AbstractFactory,生成一系列具体产品。
  • AbstractProduct:抽象产品接口/类,定义共性功能。
  • ConcreteProduct:具体产品,实现抽象产品,添加特有细节。

经典代码示例

在这里插入图片描述

// 抽象产品接口
public interface Chair { void sit(); }
public interface Sofa  { void lie();  }
public interface Table { void use();  }

// 抽象工厂
public abstract class AbstractFactory {
    abstract Chair createChair();
    abstract Sofa createSofa();
    abstract Table createTable();
}

// 具体工厂:中式家具
public class ChinaFactory extends AbstractFactory {
    @Override public Chair createChair() { return new ChinaChair(); }
    @Override public Sofa createSofa()   { return new ChinaSofa(); }
    @Override public Table createTable() { return new ChinaTable(); }
}

// 具体产品:中式椅子
public class ChinaChair implements Chair {
    public void sit() { System.out.println("中式椅子:榉木坐享"); }
}
// …… USAFactory、USAChair 等类似

// 客户端
public class Client {
    private Chair chair; 
    private Sofa sofa; 
    private Table table;
    public Client(AbstractFactory f) {
        chair = f.createChair();
        sofa  = f.createSofa();
        table = f.createTable();
    }
    public void useAll() {
        chair.sit(); 
        sofa.lie(); 
        table.use();
    }
}

隐藏的变化与抽象产品的重要性

抽象工厂向客户端隐藏了:

  1. 支持的工厂集合 数目;
  2. 当前使用的是哪一个具体工厂;
  3. 被实例化的具体产品类型;
  4. 实例选择的依据(环境、配置等)。

真正的核心在于找到抽象产品:只有当“椅子”“沙发”“桌子”接口足够简洁、通用,才能让具体工厂各自实现并保持一致性。


使用场景分析

  1. 跨平台兼容:选择不同 OS 驱动集(Windows、Mac、Linux)。
  2. 多产品系列:电商系统的商品、订单、物流按区域差异化实现。
  3. 插件/布局主题:UI 组件库按主题切换不同风格。
  4. JDK 案例DocumentBuilderFactoryTransformerFactory

为什么使用抽象工厂?

  1. 提升复用性:同一抽象定义可复用多套具体实现(如 JDBC 驱动)。
  2. 解耦创建与使用:客户端只依赖抽象工厂和抽象产品,无需关心具体类。
  3. 增强扩展性:新增产品系列时,只需增加具体工厂及产品类,无需改动现有代码。

优势与劣势

优势

  • 符合开闭原则:新增系列只需继承,无需修改抽象。
  • 保证同一工厂产品族内部一致性。
  • 明确单一职责:抽象工厂负责创建,产品类只关注自身功能。
  • 易于新增产品系列,满足多样化需求。

劣势

  • 增加代码量:接口与具体实现层级增多。
  • 学习成本高:正确抽象难以初步掌握。
  • 修改结构困难:若抽象产品变化,需要同步更新所有具体工厂。

总结

  • 核心精髓:正确抽象——提炼简洁通用的产品接口。
  • 设计要点:先分析共性,再分离具体;不要盲目抽象,否则模式流于形式。
  • 实践建议:从小范围组件或跨平台需求切入,逐步掌握抽象工厂思维。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小工匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值