项目地址
1. 简介
工厂方法(Factory Method)是一种创建型设计模式,通过定义一个创建对象的接口或抽象类,允许子类决定实例化的具体对象类型。
主要目标是将对象的创建延迟到子类中,从而使父类不必知道具体产品对象的创建细节。这种设计提供了灵活的方式来扩展和维护代码,因为产品的具体实现可以在不修改现有代码的情况下轻松扩展。
工厂方法模式特别适用于需要通过继承来创建类的实例,并且不影响其使用方式的场景。它在需要灵活扩展产品类型的情况下非常有用,因为它允许开发者在不修改现有代码的情况下添加新的产品类型。
2. 核心思想
• 延迟实例化:将对象的实例化过程推迟到子类中进行,这样可以实现更高的灵活性和可扩展性。
• 解耦创建与使用:客户端不直接依赖于具体的产品类,而是通过工厂方法获取产品对象,减少了代码的耦合度。
3. 主要组成部分
- 产品接口(Product):定义了所有具体产品的共同行为,客户端代码通过产品接口与具体产品交互。
- 具体产品类(ConcreteProduct):实现产品接口,表示具体的产品。这些类包含了产品的具体实现。
- 抽象创建者(Creator):声明了一个返回产品对象的工厂方法,通常返回的是产品接口的实例。创建者类可以包含其他与工厂方法相关的业务逻辑。
- 具体创建者(ConcreteCreator):实现抽象创建者中的工厂方法,返回具体产品的实例。每个具体创建者对应一种具体产品。
- 客户端代码(Client):通过调用工厂方法获取产品对象,并使用该产品对象完成业务逻辑。客户端代码不直接依赖具体产品类,因而具备较高的灵活性。
4. 适应场景
工厂方法模式适用于以下场景:
- 需要在运行时决定创建对象的类型:如果一个系统在运行时需要动态地创建不同类型的对象,工厂方法模式非常适合。这种情况通常出现在需要根据不同条件(如配置文件、用户输入等)创建不同的对象时。
- 不能预先确定类的具体实现:当系统在设计阶段无法确定需要创建的对象的具体类时,工厂方法可以将创建逻辑延迟到子类中实现,以便在运行时决定创建的对象类型。
- 希望在创建对象时进行额外的配置或处理:工厂方法模式允许在对象创建时执行额外的逻辑,如初始化配置、依赖注入、日志记录等,而这些操作可以集中在工厂方法中。
- 希望隔离对象的创建过程:当对象的创建过程非常复杂或涉及多个步骤时,工厂方法可以将这些复杂性封装起来,使得调用者无需了解创建过程的细节。
举例
例如,一个应用程序可能需要支持多种日志记录方式(如文件日志、数据库日志、网络日志等)。使用工厂方法模式,可以为每种日志记录方式创建不同的子类,并在这些子类中实现具体的日志创建逻辑。如果以后需要支持新的日志记录方式,只需添加新的子类并实现相应的工厂方法,而不需要修改现有的日志记录代码。
5. 优缺点
5.1 优点
- 降低耦合度:工厂方法模式可以有效地降低创建者和具体产品之间的耦合度。父类只定义了一个创建对象的接口,而具体的实现则由子类来负责。这样,如果需要更换或新增具体产品类,只需更改子类的实现即可,无需修改父类代码。
- 单一职责原则:工厂方法模式遵循单一职责原则,因为它将产品创建的代码集中在一个位置,使得程序的其他部分不必关心对象的创建逻辑。这使得代码更容易理解和维护。
- 开闭原则:工厂方法模式很好地满足了开闭原则。通过引入新的子类来创建新类型的产品,而不需要修改现有的工厂方法,系统可以在不影响已有功能的情况下扩展新的功能。
- 灵活性:由于工厂方法模式将对象的创建延迟到子类中,程序可以灵活地添加新的产品类,同时不影响已有代码的运行。这为系统提供了极大的扩展性。
5.2 缺点
- 增加代码复杂度:由于工厂方法模式依赖于继承和多态,使用该模式可能会引入大量新的子类,从而使代码的层次结构变得复杂。这会增加代码的复杂性,特别是在需要创建大量产品类时。
- 理解和使用难度较高:对于初学者来说,理解工厂方法模式的工作原理和正确使用方式可能会有一定的难度。特别是当系统中涉及多个工厂方法和产品类时,可能会让人难以理解和维护。
6. 代码实现
6.1 类图
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.java
和ConcreteCreatorB.java
: 具体工厂类,实现了工厂方法,负责创建具体的产品对象。Product.java
: 产品接口,定义了产品的行为。ConcreteProductA.java
和ConcreteProductB.java
: 具体产品类,实现了产品接口,提供了产品的具体行为。
通过这种结构,工厂方法模式将对象的创建和使用分离,允许客户端通过工厂方法创建对象,而无需了解对象的具体实现。
7. 总结
工厂方法模式通过将对象的创建延迟到子类中实现,实现了对象创建的灵活性和系统的可扩展性。该模式降低了客户端与具体产品类之间的耦合度,遵循了开闭原则。然而,工厂方法模式的应用也可能导致代码结构复杂,需要在设计时慎重考虑其适用性。