设计模式 - 工厂模式 精准梳理&精准记忆

1、代码片段 - 带入理解

一、核心模式分类

  1. 简单工厂模式(编程习惯,非 GoF 设计模式)
  2. 工厂方法模式(GoF 创建型模式)
  3. 抽象工厂模式(GoF 创建型模式)

二、演变过程:咖啡店案例

初始实现

java 复制代码
// 咖啡基类
abstract class Coffee {
     public abstract String getName();
}

class AmericanCoffee extends Coffee {}
class LatteCoffee extends Coffee {}

// 咖啡店直接创建对象
class CoffeeStore {
     public Coffee orderCoffee(String type) {
          if ("american".equals(type)) {
               return new AmericanCoffee();
          } else {
               return new LatteCoffee();
          }
     }
}

问题 违反开闭原则,新增咖啡类型需修改订单方法


三、改进方案演变

1、简单工厂模式

java 复制代码
class SimpleCoffeeFactory {
    public Coffee createCoffee(String type) {
        // 创建逻辑...
    }
}

class CoffeeStore {
    private SimpleCoffeeFactory factory;
    public Coffee orderCoffee(String type) {
        return factory.createCoffee(type);
    }
}
  • 优点 解耦对象创建
  • 缺点 仍需修改工厂代码,违反开闭原则

2、工厂方法模式

java 复制代码
interface CoffeeFactory {
    Coffee createCoffee();
}

class AmericanFactory implements CoffeeFactory {
    public Coffee createCoffee() { return new AmericanCoffee(); }
}

class CoffeeStore {
    private CoffeeFactory factory;
    public void setFactory(CoffeeFactory factory) {
        this.factory = factory;
    }
    public Coffee orderCoffee() {
        return factory.createCoffee();
    }
}
  • 优点 完全遵循开闭原则
  • 缺点 类数量激增(类爆炸问题)

3、抽象工厂模式

java 复制代码
interface DessertFactory {
    Coffee createCoffee();
    Dessert createDessert();
}

class AmericanDessertFactory implements DessertFactory {
    public Coffee createCoffee() { return new AmericanCoffee(); }
    public Dessert createDessert() { return new MatchaMousse(); }
}
  • 优点 管理产品族(咖啡+甜点的组合)
  • 代价 新增产品类型需修改所有工厂接口

4、模式对比表

模式特性 简单工厂 工厂方法 抽象工厂
扩展性 修改工厂类 新增工厂子类 新增工厂实现类
产品维度 单一产品 单一产品 产品族(多相关产品)
开闭原则 违反 遵循 部分遵循
复杂度
典型应用场景 简单对象创建 需要灵活扩展的产品创建 系列关联产品的组合创建

四、进阶应用技巧

1、静态工厂

java 复制代码
class SimpleCoffeeFactory {
     public static Coffee createCoffee(String type) {
          // 创建逻辑...
     }
}

2、配置化工厂

properties 复制代码
# bean.properties
american=com.example.AmericanCoffee
latte=com.example.LatteCoffee
java 复制代码
class ConfigFactory {
     private static Map<String, Coffee> cache = new HashMap<>();

     static {
          // 加载配置文件,反射创建对象存入缓存
     }

     public static Coffee getCoffee(String key) {
          return cache.get(key);
     }
}

全部代码

java 复制代码
public class CoffeeFactory {
     // 加载配置文件, 获取配置文件中配置的全类名, 并创建该类的对象进行存储
     // 1.定义容器对象用来存储咖啡对象
     private static HashMap<String, Coffee> map = new HashMap<String, Coffee>();

     // 2.加载配置文件, 只需要加载一次
     static {
          // 2.1 创建proper.ties 对象
          Properties p = new Properties();
          // 2.2调用p对象中的load 方法进行配置文件的加载   获取字节码 -> 获取类加载器 -> 获取目标资源(返回inputStream)
          InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");
          try {
               // 加载资源
               p.load(is);
               // 从p集合中获取全类名并创建对象
               Set<Object> keys = p.keySet();
               for (Object key : keys) {
                    String className = p.getProperty((String) key);
                    // 通过反射创建对象
                    Class<?> clazz = Class.forName(className);
                    Coffee coffee = (Coffee) clazz.newInstance();// 创建对象
                    // 将名称和对象存储到容器中
                    map.put((String) key,coffee);
               }
          } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
               e.printStackTrace();
          }
     }

     // 根据名称获取对象
     public static Coffee createCoffee(String name){
          return map.get(name);
     }
}

五、JDK典型案例

  1. 集合迭代器
java 复制代码
// 工厂方法模式应用
Collection<String> coll = new ArrayList<>();
Iterator<String> it = coll.iterator(); // ArrayList内部实现Iterator
  1. 日期工具
java 复制代码
Calendar cal = Calendar.getInstance(); // 根据时区返回不同实现
DateFormat df = DateFormat.getInstance();

2、文字提炼 - 记忆切入点

一、简单工厂模式

1、核心思想

将对象创建逻辑集中在一个"工厂类"中,通过 参数 控制具体产品类型。

  • 关键步骤

    1. 定义产品接口

      创建抽象基类(如 Coffee),声明所有产品共有的方法(如 getName()

    2. 实现具体产品

      继承基类创建具体产品(如 AmericanCoffeeLatteCoffee),各自实现特有逻辑

    3. 构建工厂类

      创建 SimpleCoffeeFactory 类,内部包含静态/实例方法(如 createCoffee(type)),通过 if-elseswitch 判断参数类型,返回对应的具体产品实例

    4. 客户端调用

      客户端(如CoffeeStore)持有工厂引用,调用createCoffee()时传入类型参数,无需直接接触具体产品类

  • 典型特征

    • 工厂类包含所有产品的创建逻辑

    • 新增产品必须修改工厂类代码


二、工厂方法模式

2、核心思想

将对象的创建 延迟 到子类,每个产品对应一个专属工厂。

  • 关键步骤

    1. 定义抽象工厂接口

      创建CoffeeFactory接口,声明抽象方法(如createCoffee()

    2. 实现具体工厂

      为每个产品创建专属工厂类(如AmericanCoffeeFactoryLatteCoffeeFactory),在createCoffee()中返回对应的具体产品实例

    3. 客户端依赖抽象

      客户端类(如CoffeeStore)持有工厂接口的引用,通过setFactory()方法注入具体工厂

    4. 动态创建产品

      客户端调用factory.createCoffee()时,实际执行的是具体工厂类中实现的创建逻辑

  • 典型特征

    • 每个产品对应一个独立工厂类

    • 新增产品只需添加新工厂,无需修改已有代码


三、抽象工厂模式

2、核心思想

创建相关产品族的工厂,保证产品之间的兼容性。

  • 关键步骤

    1. 定义产品族接口

      创建多个抽象产品接口(如 Coffee: 咖啡Dessert: 甜点),每个接口代表一类产品

    2. 定义抽象工厂接口

      创建DessertFactory: 甜点工厂接口,声明创建系列产品的方法(如 createCoffee()createDessert()

    3. 实现具体工厂

      为每个产品族创建工厂类(如AmericanDessertFactory: 美式甜点工厂),同时实现该族内 所有产品的创建逻辑

    4. 客户端组合使用

      客户端通过选择具体工厂,获得配套的产品组合(如美式咖啡 + 抹茶慕斯),确保产品间的兼容性

  • 典型特征

    • 一个工厂创建多个关联产品

    • 新增产品类型时, 需要修改所有工厂接口


四、工厂模式历史演进

  1. 简单工厂 解决直接 new 对象带来的耦合问题,但工厂本身成为新的耦合点
  2. 工厂方法 通过多态工厂解耦,支持扩展但容易产生类爆炸
  3. 抽象工厂 应对产品组合需求,用更高维度的抽象管理关联对象

五、记忆点 - 关键区别

  • 考虑创建目标时

    • 简单工厂 单一产品
    • 工厂方法 单一产品
    • 抽象工厂 产品族
  • 考虑扩展代价时

    • 简单工厂 修改工厂类
    • 工厂方法 新增工厂类
    • 抽象工厂 修改所有工厂接口
  • 考虑设计重心时

    • 简单工厂 创建逻辑集中化
    • 工厂方法 创建责任分散化
    • 抽象工厂 产品组合约束

提炼

模式选择指南

  1. 简单工厂 适用于对象创建逻辑简单,不需要频繁扩展
  2. 工厂方法 适合需要灵活扩展产品类型的场景
  3. 抽象工厂 适用于管理产品族,强调相关产品必须配套使用

关键设计原则体现

  1. 开闭原则 工厂方法模式的典型体现
  2. 单一职责 每个工厂只负责创建特定对象
  3. 依赖倒置 客户端依赖抽象接口而非具体实现

如果这篇文章帮到你, 帮忙点个关注呗, 不想那那那点赞或收藏也行鸭 (。•̀ᴗ-)✧ ~

'(இ﹏இ`。)

相关推荐
ChinaRainbowSea12 分钟前
Linux: Centos7 Cannot find a valid baseurl for repo: base/7/x86_64 解决方案
java·linux·运维·服务器·docker·架构
囧囧 O_o13 分钟前
Java 实现 Oracle 的 MONTHS_BETWEEN 函数
java·oracle
去看日出15 分钟前
RabbitMQ消息队列中间件安装部署教程(Windows)-2025最新版详细图文教程(附所需安装包)
java·windows·中间件·消息队列·rabbitmq
计算机-秋大田18 分钟前
基于Spring Boot的宠物健康顾问系统的设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·课程设计
JouJz25 分钟前
Java虚拟机之垃圾收集(一)
java·开发语言·jvm
源码姑娘37 分钟前
基于DeepSeek的智慧医药系统(源码+部署教程)
java·人工智能·程序人生·毕业设计·springboot·健康医疗·课程设计
morris13143 分钟前
【redis】布隆过滤器的Java实现
java·redis·布隆过滤器
五行星辰1 小时前
Java链接redis
java·开发语言·redis
编程毕设1 小时前
【含文档+PPT+源码】基于微信小程序的在线考试与选课教学辅助系统
java·微信小程序·小程序
异常驯兽师1 小时前
Java集合框架深度解析:List、Set与Map的核心区别与应用指南
java·开发语言·list