JAVA设计模式-工厂方法模式

工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,但将具体创建哪个类的对象的决定权推迟到子类。其核心在于让子类来决定实例化哪一个类,从而将对象的创建与使用解耦,提高了系统的灵活性和可扩展性。

核心结构与角色

工厂方法模式主要包含以下角色,其协作关系如下图所示(以抽象概念表示):

角色 职责 说明
抽象产品 (Product) 定义产品的接口 所有具体产品必须实现的公共接口或抽象类。
具体产品 (Concrete Product) 实现抽象产品接口 工厂方法模式创建的具体对象类。
抽象工厂/创建者 (Creator) 声明工厂方法 返回一个抽象产品类型的对象。它可以包含一些依赖于产品的核心业务逻辑。
具体工厂/具体创建者 (Concrete Creator) 实现工厂方法 重写工厂方法,返回一个具体产品的实例。客户端通常与具体工厂交互。

实现原理与步骤

工厂方法模式的核心是利用多态性,将对象创建的责任从客户端代码转移到专门的工厂类中。客户端代码仅依赖于抽象产品接口和抽象工厂,无需关心具体产品的类名和创建细节。

其实现步骤如下:

  1. 定义抽象产品接口:声明所有产品对象共有的方法。
  2. 创建具体产品类:实现抽象产品接口,定义具体的产品对象。
  3. 定义抽象工厂类:声明一个返回抽象产品对象的工厂方法。该类可以包含一些不依赖于具体产品类型的核心业务逻辑。
  4. 创建具体工厂类:继承抽象工厂类,并重写工厂方法,使其返回一个具体产品的实例。

代码示例:模拟水果加工厂

以下是一个完整案例,模拟一个水果加工厂生产不同水果罐头的过程。

步骤1:定义抽象产品 (Fruit)

java 复制代码
// 抽象产品:水果
public interface Fruit {
    void produce(); // 生产水果罐头
}

步骤2:创建具体产品类 (Apple, Orange)

java 复制代码
// 具体产品:苹果罐头
public class Apple implements Fruit {
    @Override
    public void produce() {
        System.out.println("生产了一罐苹果罐头。");
    }
}

// 具体产品:橙子罐头
public class Orange implements Fruit {
    @Override
    public void produce() {
        System.out.println("生产了一罐橙子罐头。");
    }
}

步骤3:定义抽象工厂 (FruitFactory)

java 复制代码
// 抽象工厂/创建者
public abstract class FruitFactory {
    // 工厂方法:由子类实现,用于创建具体产品
    public abstract Fruit createFruit();
    
    // 可以包含一些不依赖于具体产品的业务逻辑
    public void processFruit() {
        Fruit fruit = createFruit(); // 调用工厂方法创建产品
        System.out.println("开始加工水果...");
        fruit.produce(); // 使用产品
        System.out.println("水果加工完成,准备包装。");
    }
}

步骤4:创建具体工厂类 (AppleFactory, OrangeFactory)

java 复制代码
// 具体工厂:苹果工厂
public class AppleFactory extends FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Apple(); // 工厂方法返回具体产品:苹果
    }
}

// 具体工厂:橙子工厂
public class OrangeFactory extends FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Orange(); // 工厂方法返回具体产品:橙子
    }
}

步骤5:客户端使用

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 客户端代码依赖于抽象工厂和抽象产品,而非具体类
        FruitFactory appleFactory = new AppleFactory();
        appleFactory.processFruit(); // 输出:开始加工水果... 生产了一罐苹果罐头。 水果加工完成,准备包装。

        FruitFactory orangeFactory = new OrangeFactory();
        orangeFactory.processFruit(); // 输出:开始加工水果... 生产了一罐橙子罐头。 水果加工完成,准备包装。
        
        // 如果需要新增产品,例如香蕉
        // 1. 新增具体产品类 Banana implements Fruit
        // 2. 新增具体工厂类 BananaFactory extends FruitFactory
        // 3. 客户端使用:FruitFactory bananaFactory = new BananaFactory();
        // 原有代码(抽象工厂、其他具体工厂、客户端调用逻辑)完全不需要修改,符合"开闭原则"。
    }
}

模式对比:工厂方法 vs. 简单工厂

工厂方法模式常与简单工厂模式(静态工厂方法)对比。简单工厂将所有创建逻辑集中在一个工厂类中,通过传入参数决定创建何种产品。

java 复制代码
// 简单工厂示例
public class SimpleFruitFactory {
    public static Fruit createFruit(String type) {
        if ("apple".equalsIgnoreCase(type)) {
            return new Apple();
        } else if ("orange".equalsIgnoreCase(type)) {
            return new Orange();
        }
        throw new IllegalArgumentException("Unknown fruit type");
    }
}
// 使用:Fruit apple = SimpleFruitFactory.createFruit("apple");

对比分析

  • 简单工厂 :优点是将创建逻辑封装,客户端无需知道具体类名。缺点是违反了开闭原则 ,当需要新增产品时,必须修改工厂类的 createFruit 方法(增加新的 if-else 分支)。
  • 工厂方法 :将创建逻辑分散到各个具体工厂中。新增产品时,只需增加新的具体产品类和对应的具体工厂类,无需修改任何现有工厂代码,完全符合开闭原则,系统扩展性更强。

应用场景与优势

工厂方法模式适用于以下场景:

  1. 无法预知对象确切类型:当编写代码时,无法预知将要创建的对象的具体类,需要由运行时条件决定。
  2. 希望将产品创建与使用解耦 :避免在业务代码中直接使用 new 关键字创建具体对象,降低模块间的耦合度。
  3. 系统需要良好的扩展性:预计未来会频繁新增产品种类。
  4. 复用对象创建过程:当对象的创建过程复杂(如需要配置、依赖其他服务)时,可以在工厂方法中封装这些过程,便于复用。

优势包括:

  • 符合开闭原则:新增产品类型时,只需扩展新的具体工厂和产品类,无需修改客户端和现有工厂代码。
  • 单一职责原则:将产品创建代码集中在工厂类中,使得代码更易维护。
  • 解耦 :客户端代码仅依赖于抽象接口(FruitFruitFactory),与具体实现分离,提高了代码的灵活性和可测试性。

缺点

  • 类的数量增加:每增加一个产品,通常就需要增加一个具体产品类和一个具体工厂类,可能导致系统类数量膨胀,增加复杂度。

在Java生态中的应用实例

  1. Java集合框架java.util.Collection 接口的 iterator() 方法就是一个工厂方法。ArrayListHashSet 等具体集合类重写此方法,分别返回 ItrKeyIterator 等不同的具体迭代器产品。
  2. Spring FrameworkBeanFactoryApplicationContext 是核心容器,它们使用工厂方法模式来创建和管理Bean对象。例如,ApplicationContextgetBean() 方法根据配置信息(如XML、注解)动态创建并返回所需的对象实例。
  3. 日志框架 :如SLF4J的 LoggerFactory.getLogger() 方法。根据底层绑定的具体日志实现(Logback、Log4j2),该方法返回对应的Logger产品实例。

总结

工厂方法模式通过引入"工厂"这一抽象层 ,将对象的实例化过程封装起来,使系统在不修改现有代码的前提下,能够应对变化和扩展。它是实现依赖倒置原则开闭原则的经典范例。在选择使用时,如果产品结构相对稳定,新增不频繁,简单工厂可能更简洁;如果系统需要高度可扩展,产品种类可能频繁增加,工厂方法模式是更优的选择。在实际开发中,结合Spring等IoC容器,可以更加优雅地实现和管理工厂方法模式。


参考来源

相关推荐
千云2 小时前
问题排查报告:一次因元空间溢出导致的CPU飙升与接口超时
java·后端
Full Stack Developme2 小时前
MyBatis-Plus 注解教程
java·spring·mybatis
程序员三明治2 小时前
【AI】Java 调用大模型 API 实战:从 OpenAI 协议到 SiliconFlow 流式响应解析
java·开发语言·人工智能
2501_913061342 小时前
JVM虚拟机——面试中的八股文
java·jvm·面试
A-Jie-Y2 小时前
JAVA设计模式-单例模式
java·设计模式
编程之升级打怪2 小时前
设计模板引擎类的主要接口
java
ffqws_2 小时前
Spring Boot 整合 PageHelper 实现分页查询
java·spring boot·mybatis
大龄码农-涵哥2 小时前
Java调用AI大模型API入门:从零开始接入ChatGPT/通义千问
java·人工智能·chatgpt
ch.ju3 小时前
Java程序设计(第3版)第二章——for嵌套输出图形
java