wangguangwu
wangguangwu
发布于 2024-08-21 / 29 阅读
0
0

创建型模式-工厂方法

项目地址

创建型模式-工厂方法

1. 简介

工厂方法(Factory Method)是一种创建型设计模式,通过定义一个创建对象的接口或抽象类,允许子类决定实例化的具体对象类型。

主要目标是将对象的创建延迟到子类中,从而使父类不必知道具体产品对象的创建细节。这种设计提供了灵活的方式来扩展和维护代码,因为产品的具体实现可以在不修改现有代码的情况下轻松扩展。

工厂方法模式特别适用于需要通过继承来创建类的实例,并且不影响其使用方式的场景。它在需要灵活扩展产品类型的情况下非常有用,因为它允许开发者在不修改现有代码的情况下添加新的产品类型。

2. 核心思想

延迟实例化:将对象的实例化过程推迟到子类中进行,这样可以实现更高的灵活性和可扩展性。
解耦创建与使用:客户端不直接依赖于具体的产品类,而是通过工厂方法获取产品对象,减少了代码的耦合度。

3. 主要组成部分

  1. 产品接口(Product):定义了所有具体产品的共同行为,客户端代码通过产品接口与具体产品交互。
  2. 具体产品类(ConcreteProduct):实现产品接口,表示具体的产品。这些类包含了产品的具体实现。
  3. 抽象创建者(Creator):声明了一个返回产品对象的工厂方法,通常返回的是产品接口的实例。创建者类可以包含其他与工厂方法相关的业务逻辑。
  4. 具体创建者(ConcreteCreator):实现抽象创建者中的工厂方法,返回具体产品的实例。每个具体创建者对应一种具体产品。
  5. 客户端代码(Client):通过调用工厂方法获取产品对象,并使用该产品对象完成业务逻辑。客户端代码不直接依赖具体产品类,因而具备较高的灵活性。

4. 适应场景

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

  1. 需要在运行时决定创建对象的类型:如果一个系统在运行时需要动态地创建不同类型的对象,工厂方法模式非常适合。这种情况通常出现在需要根据不同条件(如配置文件、用户输入等)创建不同的对象时。
  2. 不能预先确定类的具体实现:当系统在设计阶段无法确定需要创建的对象的具体类时,工厂方法可以将创建逻辑延迟到子类中实现,以便在运行时决定创建的对象类型。
  3. 希望在创建对象时进行额外的配置或处理:工厂方法模式允许在对象创建时执行额外的逻辑,如初始化配置、依赖注入、日志记录等,而这些操作可以集中在工厂方法中。
  4. 希望隔离对象的创建过程:当对象的创建过程非常复杂或涉及多个步骤时,工厂方法可以将这些复杂性封装起来,使得调用者无需了解创建过程的细节。

举例

例如,一个应用程序可能需要支持多种日志记录方式(如文件日志、数据库日志、网络日志等)。使用工厂方法模式,可以为每种日志记录方式创建不同的子类,并在这些子类中实现具体的日志创建逻辑。如果以后需要支持新的日志记录方式,只需添加新的子类并实现相应的工厂方法,而不需要修改现有的日志记录代码。

5. 优缺点

5.1 优点

  1. 降低耦合度:工厂方法模式可以有效地降低创建者和具体产品之间的耦合度。父类只定义了一个创建对象的接口,而具体的实现则由子类来负责。这样,如果需要更换或新增具体产品类,只需更改子类的实现即可,无需修改父类代码。
  2. 单一职责原则:工厂方法模式遵循单一职责原则,因为它将产品创建的代码集中在一个位置,使得程序的其他部分不必关心对象的创建逻辑。这使得代码更容易理解和维护。
  3. 开闭原则:工厂方法模式很好地满足了开闭原则。通过引入新的子类来创建新类型的产品,而不需要修改现有的工厂方法,系统可以在不影响已有功能的情况下扩展新的功能。
  4. 灵活性:由于工厂方法模式将对象的创建延迟到子类中,程序可以灵活地添加新的产品类,同时不影响已有代码的运行。这为系统提供了极大的扩展性。

5.2 缺点

  1. 增加代码复杂度:由于工厂方法模式依赖于继承和多态,使用该模式可能会引入大量新的子类,从而使代码的层次结构变得复杂。这会增加代码的复杂性,特别是在需要创建大量产品类时。
  2. 理解和使用难度较高:对于初学者来说,理解工厂方法模式的工作原理和正确使用方式可能会有一定的难度。特别是当系统中涉及多个工厂方法和产品类时,可能会让人难以理解和维护。

6. 代码实现

6.1 类图

Pasted image 20240821114034.png

6.2 类结构

.
└── com
    └── wangguangwu
        ├── Client.java
        ├── factory
        │   ├── ConcreteCreatorA.java
        │   ├── ConcreteCreatorB.java
        │   └── Creator.java
        └── product
            ├── Product.java
            └── impl
                ├── ConcreteProductA.java
                └── ConcreteProductB.java

6.3 代码解析

这是一个基于工厂方法设计模式的 Java 代码结构。下面是对每个类的解释:

6.3.1 Client.java

  • 位置: com.wangguangwu.Client
  • 角色: 客户端代码。
  • 说明: 这是工厂方法模式的客户端类,负责调用工厂方法来创建产品对象。客户端通常不直接实例化产品,而是通过调用工厂方法来获取产品对象,然后调用产品的方法。

6.3.2 factory 包

这个包内的类负责定义和实现创建产品的工厂类。

  • Creator.java

    • 位置: com.wangguangwu.factory.Creator
    • 角色: 抽象创建者类。
    • 说明: 定义了工厂方法(createProduct()),该方法返回一个 Product 类型的对象。子类需要实现这个工厂方法来创建具体的产品。它还可能包含一些与产品创建无关的逻辑。
  • ConcreteCreatorA.java

    • 位置: com.wangguangwu.factory.ConcreteCreatorA
    • 角色: 具体创建者类 A。
    • 说明: 继承自 Creator,实现了工厂方法 createProduct(),负责创建 ConcreteProductA 类型的产品。
  • ConcreteCreatorB.java

    • 位置: com.wangguangwu.factory.ConcreteCreatorB
    • 角色: 具体创建者类 B。
    • 说明: 继承自 Creator,实现了工厂方法 createProduct(),负责创建 ConcreteProductB 类型的产品。

6.3.3 product 包

这个包内的类负责定义产品及其具体实现。

  • Product.java

    • 位置: com.wangguangwu.product.Product
    • 角色: 产品接口。
    • 说明: 定义了产品的接口(doStuff()),所有的具体产品类都需要实现这个接口。
  • impl 包

    • 位置: com.wangguangwu.product.impl

    • 这个子包内的类是 Product 接口的具体实现类。

    • ConcreteProductA.java

      • 位置: com.wangguangwu.product.impl.ConcreteProductA
      • 角色: 具体产品 A。
      • 说明: 实现了 Product 接口,定义了 doStuff() 方法的具体逻辑,代表某种具体类型的产品。
    • ConcreteProductB.java

      • 位置: com.wangguangwu.product.impl.ConcreteProductB
      • 角色: 具体产品 B。
      • 说明: 实现了 Product 接口,定义了 doStuff() 方法的具体逻辑,代表另一种具体类型的产品。

总结:

  • Client.java: 客户端代码,使用工厂方法来创建和使用产品对象。
  • Creator.java: 抽象工厂类,定义了创建产品的方法。
  • ConcreteCreatorA.javaConcreteCreatorB.java: 具体工厂类,实现了工厂方法,负责创建具体的产品对象。
  • Product.java: 产品接口,定义了产品的行为。
  • ConcreteProductA.javaConcreteProductB.java: 具体产品类,实现了产品接口,提供了产品的具体行为。

通过这种结构,工厂方法模式将对象的创建和使用分离,允许客户端通过工厂方法创建对象,而无需了解对象的具体实现。

7. 总结

工厂方法模式通过将对象的创建延迟到子类中实现,实现了对象创建的灵活性和系统的可扩展性。该模式降低了客户端与具体产品类之间的耦合度,遵循了开闭原则。然而,工厂方法模式的应用也可能导致代码结构复杂,需要在设计时慎重考虑其适用性。


评论