简介:工厂模式是Java中一种重要的创建型设计模式,旨在将对象的创建过程封装,降低代码耦合度,提升灵活性。主要分为简单工厂、工厂方法和抽象工厂三种类型,分别适用于不同复杂度的业务场景。本案例通过详细讲解三种工厂模式的实现原理与使用场景,结合数据库连接池、GUI组件创建等实际应用,帮助开发者掌握如何在项目中灵活运用工厂模式,提升代码的可维护性与可扩展性。
1. 工厂模式概述与核心思想
工厂模式(Factory Pattern)是面向对象设计中最常用的设计模式之一,属于创建型模式范畴。其核心思想在于 将对象的创建过程封装到工厂类中,使客户端代码与具体类的实现解耦 。通过引入工厂类,系统在扩展新对象类型时无需修改原有调用逻辑,符合开闭原则(Open-Closed Principle)。
在实际开发中,特别是在Java项目中,工厂模式广泛应用于需要动态创建对象、屏蔽具体实现细节、提升系统可维护性的场景。例如,数据库连接管理、跨平台UI控件创建、以及Spring框架中的Bean管理等。掌握工厂模式的核心思想,是深入理解软件设计解耦与扩展性的关键一步。
2. 工厂模式的基本分类与实现原理
工厂模式作为设计模式中的创建型模式,主要解决对象创建过程中的耦合问题。在实际开发中,工厂模式根据其复杂程度和应用场景的不同,可分为三种主要类型: 简单工厂模式 、 工厂方法模式 和 抽象工厂模式 。本章将围绕这三种模式展开深入分析,从结构设计、实现原理到优缺点对比,帮助读者全面掌握工厂模式的核心实现机制与适用场景。
2.1 简单工厂模式
简单工厂模式(Simple Factory Pattern)是最基础的工厂模式实现形式,它通过一个统一的工厂类来负责创建所有具体产品对象。该模式在结构上较为简洁,适用于产品种类相对固定、不频繁变化的场景。
2.1.1 简单工厂的结构与角色划分
简单工厂模式通常包含以下几个核心角色:
- Factory(工厂类) :负责创建产品的类,根据传入的参数决定创建哪一类产品。
- Product(抽象产品) :定义产品的公共接口,是所有具体产品的父类。
- ConcreteProduct(具体产品) :实现抽象产品接口的具体类,代表不同的产品类型。
以下是简单工厂模式的类图结构(使用Mermaid绘制):
classDiagram
class Product {
<<interface>>
+operation()
}
class ConcreteProductA {
+operation()
}
class ConcreteProductB {
+operation()
}
class SimpleFactory {
+createProduct(type: String): Product
}
SimpleFactory --> Product
ConcreteProductA --> Product
ConcreteProductB --> Product
从图中可以看出, SimpleFactory 类通过 createProduct() 方法根据传入的参数创建不同类型的 Product 对象。这种设计将对象的创建逻辑集中在一个类中,降低了调用者对具体产品类的依赖。
2.1.2 简单工厂的实现方式
下面是一个使用 Java 实现的简单工厂模式示例:
// 抽象产品接口
interface Product {
void operation();
}
// 具体产品A
class ConcreteProductA implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductA is operating.");
}
}
// 具体产品B
class ConcreteProductB implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductB is operating.");
}
}
// 简单工厂类
class SimpleFactory {
public Product createProduct(String type) {
switch (type) {
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new IllegalArgumentException("Invalid product type");
}
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
Product productA = factory.createProduct("A");
productA.operation(); // 输出:ConcreteProductA is operating.
Product productB = factory.createProduct("B");
productB.operation(); // 输出:ConcreteProductB is operating.
}
}
代码逻辑逐行分析:
-
Product接口定义了所有产品的公共操作方法operation()。 -
ConcreteProductA和ConcreteProductB实现了Product接口,并提供具体的业务逻辑。 -
SimpleFactory类封装了对象创建逻辑,根据传入的字符串参数决定创建哪类对象。 - 在
Client中,通过调用SimpleFactory的createProduct()方法获得产品实例,并调用其方法。
这种方式将对象的创建过程集中管理,调用者无需了解具体类的实现细节,只需通过工厂接口获取产品即可。
2.1.3 简单工厂的优缺点分析
优点:
- 解耦性强 :客户端不依赖具体产品类,仅依赖工厂类和产品接口。
- 集中管理创建逻辑 :所有对象的创建都由一个类统一管理,便于维护。
- 简化客户端代码 :客户端无需关心对象创建的细节,提高代码可读性。
缺点:
- 违反开闭原则 :新增产品时需要修改工厂类的
createProduct()方法,不符合“对扩展开放,对修改关闭”的设计原则。 - 可扩展性差 :当产品种类较多或频繁变化时,工厂类会变得臃肿,难以维护。
- 职责过重 :工厂类承担了所有创建逻辑,职责单一性差,不符合单一职责原则。
适用场景:
- 产品种类固定、不频繁变化的系统。
- 客户端希望屏蔽对象创建细节,只关注产品行为。
- 需要快速实现对象创建逻辑,但对扩展性要求不高的项目。
| 特性 | 优点 | 缺点 |
|---|---|---|
| 耦合性 | 低,客户端与产品解耦 | 工厂类与产品类强耦合 |
| 可扩展性 | 差,新增产品需修改工厂类 | 适合产品固定不变的场景 |
| 职责划分 | 集中创建逻辑 | 职责过重,违反单一职责原则 |
| 开闭原则支持 | 不支持 | 不符合设计模式最佳实践 |
2.2 工厂方法模式
工厂方法模式(Factory Method Pattern)是对简单工厂模式的改进版本,它通过将对象的创建延迟到子类来实现更灵活的扩展机制。与简单工厂不同,工厂方法模式使用一个接口或抽象类来定义工厂方法,具体的创建逻辑由子类实现。
2.2.1 工厂方法模式的定义与结构
工厂方法模式的核心结构包括以下角色:
- Product(抽象产品) :定义产品接口,是所有具体产品的公共父类。
- ConcreteProduct(具体产品) :实现抽象产品接口的具体类。
- Factory(抽象工厂) :定义一个用于创建产品的抽象方法,具体实现由子类完成。
- ConcreteFactory(具体工厂) :实现抽象工厂接口,负责创建对应的具体产品。
类图结构如下(使用Mermaid绘制):
classDiagram
class Product {
<<interface>>
+operation()
}
class ConcreteProductA {
+operation()
}
class ConcreteProductB {
+operation()
}
class Factory {
<<interface>>
+factoryMethod(): Product
}
class ConcreteFactoryA {
+factoryMethod(): Product
}
class ConcreteFactoryB {
+factoryMethod(): Product
}
Factory --> Product
ConcreteFactoryA --> Factory
ConcreteFactoryB --> Factory
ConcreteProductA --> Product
ConcreteProductB --> Product
从图中可以看出,每个具体工厂类都对应一个具体产品类,通过实现 factoryMethod() 方法来创建产品对象。
2.2.2 工厂方法的实现机制
下面是一个使用 Java 实现的工厂方法模式示例:
// 抽象产品
interface Product {
void operation();
}
// 具体产品A
class ConcreteProductA implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductA is operating.");
}
}
// 具体产品B
class ConcreteProductB implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductB is operating.");
}
}
// 抽象工厂接口
interface Factory {
Product factoryMethod();
}
// 具体工厂A
class ConcreteFactoryA implements Factory {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}
// 具体工厂B
class ConcreteFactoryB implements Factory {
@Override
public Product factoryMethod() {
return new ConcreteProductB();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Product productA = factoryA.factoryMethod();
productA.operation(); // 输出:ConcreteProductA is operating.
Factory factoryB = new ConcreteFactoryB();
Product productB = factoryB.factoryMethod();
productB.operation(); // 输出:ConcreteProductB is operating.
}
}
代码逻辑逐行分析:
-
Product接口定义了产品的公共操作方法operation()。 -
ConcreteProductA和ConcreteProductB分别实现接口,并提供具体逻辑。 -
Factory接口定义了factoryMethod()方法,作为产品创建的入口。 -
ConcreteFactoryA和ConcreteFactoryB实现Factory接口,分别创建对应的产品实例。 - 在
Client中,通过具体工厂实例调用factoryMethod()获取产品对象,并执行操作。
这种方式将对象的创建逻辑分散到不同的工厂类中,提高了系统的扩展性与灵活性。
2.2.3 工厂方法与简单工厂的对比
| 特性 | 简单工厂模式 | 工厂方法模式 |
|---|---|---|
| 对象创建方式 | 由一个工厂类集中创建 | 由多个具体工厂类分散创建 |
| 扩展性 | 差,新增产品需修改工厂类 | 好,新增产品只需添加新的工厂和产品类 |
| 职责划分 | 工厂类职责单一性差 | 工厂类职责单一、清晰 |
| 开闭原则支持 | 不支持 | 支持 |
| 使用复杂度 | 简单,适合产品种类少的场景 | 稍复杂,适合产品种类多或需要扩展的项目 |
工厂方法模式通过将创建逻辑交给子类实现,使得系统更符合开闭原则,适合产品种类较多或需要频繁扩展的场景。而简单工厂适用于产品种类少、不经常变动的项目。
2.3 抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是工厂模式中最高级的实现形式,它用于创建一组相关或相互依赖的对象家族。与工厂方法模式不同,抽象工厂不仅关注单一产品的创建,还关注产品族之间的协调关系。
2.3.1 抽象工厂模式的定义与结构
抽象工厂模式通常包括以下角色:
- AbstractFactory(抽象工厂) :定义一组创建产品族的方法,每个方法创建一个特定类型的产品。
- ConcreteFactory(具体工厂) :实现抽象工厂接口,创建具体产品族中的各个产品。
- AbstractProduct(抽象产品) :定义产品的公共接口,如产品A、产品B等。
- ConcreteProduct(具体产品) :实现抽象产品接口,属于不同的产品族。
类图结构如下(使用Mermaid绘制):
classDiagram
class AbstractFactory {
<<interface>>
+createProductA(): AbstractProductA
+createProductB(): AbstractProductB
}
class ConcreteFactory1 {
+createProductA(): ConcreteProductA1
+createProductB(): ConcreteProductB1
}
class ConcreteFactory2 {
+createProductA(): ConcreteProductA2
+createProductB(): ConcreteProductB2
}
class AbstractProductA {
<<interface>>
+operationA()
}
class AbstractProductB {
<<interface>>
+operationB()
}
class ConcreteProductA1 {
+operationA()
}
class ConcreteProductB1 {
+operationB()
}
class ConcreteProductA2 {
+operationA()
}
class ConcreteProductB2 {
+operationB()
}
AbstractFactory --> AbstractProductA
AbstractFactory --> AbstractProductB
ConcreteFactory1 --> AbstractFactory
ConcreteFactory2 --> AbstractFactory
ConcreteProductA1 --> AbstractProductA
ConcreteProductB1 --> AbstractProductB
ConcreteProductA2 --> AbstractProductA
ConcreteProductB2 --> AbstractProductB
该图展示了两个具体工厂分别创建两组产品族中的产品。
2.3.2 抽象工厂的实现方式
下面是一个使用 Java 实现的抽象工厂模式示例:
// 抽象产品A
interface AbstractProductA {
void operationA();
}
// 抽象产品B
interface AbstractProductB {
void operationB();
}
// 具体产品A1
class ConcreteProductA1 implements AbstractProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA1 is operating.");
}
}
// 具体产品B1
class ConcreteProductB1 implements AbstractProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB1 is operating.");
}
}
// 具体产品A2
class ConcreteProductA2 implements AbstractProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA2 is operating.");
}
}
// 具体产品B2
class ConcreteProductB2 implements AbstractProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB2 is operating.");
}
}
// 抽象工厂接口
interface AbstractFactory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
AbstractProductA productA1 = factory1.createProductA();
AbstractProductB productB1 = factory1.createProductB();
productA1.operationA(); // 输出:ConcreteProductA1 is operating.
productB1.operationB(); // 输出:ConcreteProductB1 is operating.
AbstractFactory factory2 = new ConcreteFactory2();
AbstractProductA productA2 = factory2.createProductA();
AbstractProductB productB2 = factory2.createProductB();
productA2.operationA(); // 输出:ConcreteProductA2 is operating.
productB2.operationB(); // 输出:ConcreteProductB2 is operating.
}
}
代码逻辑逐行分析:
- 定义两个抽象产品接口
AbstractProductA和AbstractProductB。 - 创建具体产品类
ConcreteProductA1、ConcreteProductB1、ConcreteProductA2和ConcreteProductB2。 -
AbstractFactory接口定义了创建产品A和产品B的抽象方法。 -
ConcreteFactory1和ConcreteFactory2实现接口,分别返回对应的产品实例。 - 客户端通过不同工厂创建不同产品族的对象,并调用其方法。
该实现方式适用于需要创建多个相关产品对象的场景,例如不同平台下的 UI 控件、数据库连接等。
2.3.3 抽象工厂的应用场景与限制
适用场景:
- 需要创建一组具有相关性或依赖关系的产品族。
- 多平台系统中,如跨平台 GUI 组件、数据库连接器等。
- 系统需要隔离具体类的创建过程,仅通过接口进行交互。
限制:
- 新增产品族需要修改抽象工厂接口,不符合开闭原则。
- 产品族结构复杂时,类的数量迅速增加,系统复杂度提高。
- 产品族中产品种类固定,不适合产品种类频繁变化的系统。
| 特性 | 优点 | 缺点 |
|---|---|---|
| 耦合性 | 低,客户端与具体类解耦 | 工厂类与产品族耦合 |
| 可扩展性 | 一般,新增产品族需修改接口 | 产品种类固定,扩展受限 |
| 职责划分 | 工厂职责明确,产品族协调良好 | 类结构复杂 |
| 开闭原则支持 | 不完全支持 | 不符合设计模式最佳实践 |
抽象工厂模式适用于产品族固定、需要协调创建多个相关对象的系统。在实际开发中,该模式常用于构建平台适配器、组件库等复杂系统结构。
3. 工厂模式在Java中的具体实现案例
在Java开发实践中,工厂模式以其良好的解耦能力和灵活的扩展性,广泛应用于各种系统架构中。本章将通过三个典型案例,分别展示 简单工厂模式 、 工厂方法模式 和 抽象工厂模式 在Java中的具体实现方式。每个案例将从需求背景出发,设计类图结构、编写可运行的Java代码,并结合实际业务逻辑进行分析和总结。
3.1 简单工厂模式案例分析
3.1.1 案例背景与需求分析
假设我们正在开发一个电商系统,其中需要根据用户的支付方式(支付宝、微信、银联)创建不同的支付接口实现。支付接口的实现逻辑各不相同,但对外提供统一的方法调用入口。
为了提高系统的扩展性和维护性,我们决定使用 简单工厂模式 来统一管理支付对象的创建。
核心需求 :
- 用户选择支付方式后,系统能自动创建对应的支付对象。
- 各支付方式接口统一,便于统一调用。
- 后续新增支付方式时,应尽量减少对已有代码的修改。
3.1.2 代码实现与类图结构
类图结构(使用mermaid表示)
classDiagram
class Payment {
<<interface>>
+pay(amount: double)
}
class AlipayPayment
class WechatPayment
class UnionpayPayment
class PaymentFactory
PaymentFactory --> Payment : createPayment
AlipayPayment --> Payment
WechatPayment --> Payment
UnionpayPayment --> Payment
Java代码实现
// 支付接口定义
public interface Payment {
void pay(double amount);
}
// 支付宝支付实现
public class AlipayPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("支付宝支付金额:" + amount);
}
}
// 微信支付实现
public class WechatPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("微信支付金额:" + amount);
}
}
// 银联支付实现
public class UnionpayPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("银联支付金额:" + amount);
}
}
// 简单工厂类
public class PaymentFactory {
public static Payment createPayment(String type) {
switch (type) {
case "alipay":
return new AlipayPayment();
case "wechat":
return new WechatPayment();
case "unionpay":
return new UnionpayPayment();
default:
throw new IllegalArgumentException("不支持的支付类型");
}
}
}
// 客户端调用示例
public class Client {
public static void main(String[] args) {
Payment payment = PaymentFactory.createPayment("wechat");
payment.pay(100.0);
}
}
代码逻辑分析
-
Payment是支付接口,定义了统一的支付方法pay()。 -
AlipayPayment、WechatPayment、UnionpayPayment分别实现了不同支付方式的具体逻辑。 -
PaymentFactory是简单工厂类,根据传入的字符串参数决定返回哪种支付对象。 - 客户端无需关心支付对象的创建细节,只需通过工厂类获取即可。
参数说明 :
-
type:表示支付类型,支持"alipay"、"wechat"和"unionpay"。 - 若传入不支持的类型,抛出
IllegalArgumentException异常,增强系统健壮性。
3.1.3 案例总结与改进建议
优点 :
- 实现简单,适合业务逻辑不复杂、对象种类不多的场景。
- 客户端与具体类解耦,提升可维护性。
缺点 :
- 所有创建逻辑集中在工厂类中,违反开闭原则。
- 新增支付方式时需修改工厂类,存在耦合风险。
改进建议 :
- 若支付方式频繁变动,建议使用 工厂方法模式 或 配置+反射机制 动态加载类。
- 可结合Spring IOC实现更灵活的对象管理。
3.2 工厂方法模式案例详解
3.2.1 案例需求与业务逻辑设计
我们继续以支付系统为例,但这次需求更复杂:不同国家的用户可能需要使用不同的支付方式(如中国用支付宝,美国用PayPal,欧洲用Stripe),并且每种支付方式的实现逻辑也不尽相同。
此时,我们希望系统能根据不同地区自动选择对应的支付工厂,从而创建该地区支持的支付方式。这正是 工厂方法模式 的典型应用场景。
目标 :
- 不同地区对应不同的支付工厂。
- 每个工厂负责创建该地区支持的支付方式。
- 扩展性好,新增地区和支付方式时,尽量不修改已有代码。
3.2.2 工厂方法的代码实现与测试
类图结构(使用mermaid表示)
classDiagram
class Payment {
<<interface>>
+pay(amount: double)
}
class ChinaPaymentFactory
class USPaymentFactory
class EuropePaymentFactory
class AbstractPaymentFactory {
<<abstract>>
+createPayment(): Payment
}
AbstractPaymentFactory <|-- ChinaPaymentFactory
AbstractPaymentFactory <|-- USPaymentFactory
AbstractPaymentFactory <|-- EuropePaymentFactory
ChinaPaymentFactory --> AlipayPayment
USPaymentFactory --> PayPalPayment
EuropePaymentFactory --> StripePayment
AlipayPayment --> Payment
PayPalPayment --> Payment
StripePayment --> Payment
Java代码实现
// 支付接口
public interface Payment {
void pay(double amount);
}
// 支付宝支付
public class AlipayPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("支付宝支付金额:" + amount);
}
}
// PayPal支付
public class PayPalPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("PayPal支付金额:" + amount);
}
}
// Stripe支付
public class StripePayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("Stripe支付金额:" + amount);
}
}
// 抽象工厂类
public abstract class AbstractPaymentFactory {
public abstract Payment createPayment();
}
// 中国支付工厂
public class ChinaPaymentFactory extends AbstractPaymentFactory {
@Override
public Payment createPayment() {
return new AlipayPayment();
}
}
// 美国支付工厂
public class USPaymentFactory extends AbstractPaymentFactory {
@Override
public Payment createPayment() {
return new PayPalPayment();
}
}
// 欧洲支付工厂
public class EuropePaymentFactory extends AbstractPaymentFactory {
@Override
public Payment createPayment() {
return new StripePayment();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
AbstractPaymentFactory factory = new ChinaPaymentFactory();
Payment payment = factory.createPayment();
payment.pay(200.0);
}
}
代码逻辑分析
-
AbstractPaymentFactory是抽象工厂类,定义了一个创建支付对象的抽象方法。 - 每个子类(如
ChinaPaymentFactory)实现该方法,返回该地区对应的支付对象。 - 客户端通过具体工厂类获取支付对象,从而实现解耦。
参数说明 :
-
createPayment()方法返回具体的支付实现类。 - 客户端无需知道具体支付类,只需通过工厂获取即可。
3.2.3 案例中的扩展性与维护性分析
扩展性 :
- 新增地区或支付方式时,只需继承抽象工厂并实现新支付类即可。
- 遵循开闭原则,新增功能无需修改已有代码。
维护性 :
- 每个工厂负责单一地区的支付方式,职责清晰。
- 如果某个地区的支付逻辑变更,只需修改对应的工厂和支付类。
适用场景 :
- 产品种类较少,但产品族(如地区)较多。
- 不同产品族之间存在逻辑差异,需独立管理。
3.3 抽象工厂模式实战演示
3.3.1 跨平台产品族的创建案例
我们继续深入案例场景:现在系统不仅支持多种支付方式,还需要支持不同平台的UI组件(如桌面端、移动端)。每种平台下,按钮和输入框的样式和实现方式不同,但对外提供统一的接口。
这种“跨平台+产品族”的结构非常适合使用 抽象工厂模式 来实现。
目标 :
- 为桌面端和移动端分别创建一套UI组件。
- 各平台组件风格统一,内部实现不同。
- 后续新增平台时,不修改已有代码。
3.3.2 抽象工厂模式的代码实现
类图结构(使用mermaid表示)
classDiagram
class UIFactory {
<<abstract>>
+createButton(): Button
+createInput(): Input
}
class DesktopFactory
class MobileFactory
DesktopFactory --> UIFactory
MobileFactory --> UIFactory
Button <|-- WindowsButton
Button <|-- IosButton
Input <|-- WindowsInput
Input <|-- IosInput
DesktopFactory --> WindowsButton
DesktopFactory --> WindowsInput
MobileFactory --> IosButton
MobileFactory --> IosInput
Java代码实现
// 按钮接口
public interface Button {
void render();
}
// 输入框接口
public interface Input {
void render();
}
// Windows按钮实现
public class WindowsButton implements Button {
@Override
public void render() {
System.out.println("Windows风格按钮");
}
}
// iOS按钮实现
public class IosButton implements Button {
@Override
public void render() {
System.out.println("iOS风格按钮");
}
}
// Windows输入框实现
public class WindowsInput implements Input {
@Override
public void render() {
System.out.println("Windows风格输入框");
}
}
// iOS输入框实现
public class IosInput implements Input {
@Override
public void render() {
System.out.println("iOS风格输入框");
}
}
// 抽象工厂接口
public abstract class UIFactory {
public abstract Button createButton();
public abstract Input createInput();
}
// 桌面端工厂
public class DesktopFactory extends UIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public Input createInput() {
return new WindowsInput();
}
}
// 移动端工厂
public class MobileFactory extends UIFactory {
@Override
public Button createButton() {
return new IosButton();
}
@Override
public Input createInput() {
return new IosInput();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
UIFactory factory = new MobileFactory();
Button button = factory.createButton();
Input input = factory.createInput();
button.render();
input.render();
}
}
代码逻辑分析
-
UIFactory是抽象工厂,定义了创建按钮和输入框的接口。 -
DesktopFactory和MobileFactory分别实现这两个方法,返回各自平台下的组件。 - 客户端通过工厂获取组件,并调用其
render()方法。
参数说明 :
-
createButton()和createInput()方法分别创建按钮和输入框对象。 - 客户端通过
render()方法统一调用组件渲染逻辑。
3.3.3 实际开发中的使用场景与优化策略
使用场景 :
- 需要创建一组相关或依赖对象的家族(如UI组件、数据库驱动等)。
- 产品族之间存在统一的接口,但具体实现不同。
优化策略 :
- 可结合工厂配置(如XML或注解)动态加载不同工厂,避免硬编码。
- 使用Spring框架中的 BeanFactory 或 AbstractFactoryBean 来管理工厂实例。
- 对于多变的UI组件,可以使用 策略模式 配合抽象工厂进一步解耦。
优缺点 :
| 优点 | 缺点 |
|---|---|
| 统一管理产品族,确保组件一致性 | 增加新组件时需修改所有工厂类 |
| 遵循开闭原则,易于扩展 | 接口层级复杂,学习成本高 |
本章通过三个典型场景,分别展示了简单工厂、工厂方法和抽象工厂模式在Java中的具体实现。下一章我们将对比分析这些模式的差异与适用性,帮助读者在不同项目背景下做出合理选择。
4. 不同工厂模式之间的对比分析
在工厂模式的体系中,简单工厂、工厂方法与抽象工厂是三种核心实现方式,它们在结构设计、扩展能力、职责划分和适用场景上各具特色。理解这些差异不仅有助于我们在实际项目中做出合理的设计决策,还能提升我们对面向对象设计原则的理解。
4.1 简单工厂与工厂方法的对比
在工厂模式的家族中, 简单工厂(Simple Factory) 和 工厂方法(Factory Method) 是最常见的两种实现方式。它们都旨在将对象的创建过程封装起来,但实现方式和适用场景存在显著差异。
4.1.1 两种模式的结构差异
简单工厂结构
简单工厂的核心是一个工厂类,它根据传入的参数决定创建哪种产品。其结构通常包括:
- Product :产品接口或抽象类
- ConcreteProduct :具体产品类
- SimpleFactory :负责创建产品实例的工厂类
mermaid流程图展示:
classDiagram
class SimpleFactory {
+createProduct(type: String): Product
}
class Product {
<<interface>>
+operation()
}
class ConcreteProductA {
+operation()
}
class ConcreteProductB {
+operation()
}
SimpleFactory --> Product : creates
Product <|.. ConcreteProductA
Product <|.. ConcreteProductB
工厂方法结构
工厂方法模式引入了 工厂接口或抽象类 ,每个具体工厂负责创建一个具体产品。其结构如下:
- Product :产品接口或抽象类
- ConcreteProduct :具体产品类
- Factory :工厂接口或抽象类,声明创建产品的方法
- ConcreteFactory :具体工厂类,实现创建方法
mermaid流程图展示:
classDiagram
class Factory {
<<interface>>
+createProduct(): Product
}
class ConcreteFactoryA {
+createProduct(): Product
}
class ConcreteFactoryB {
+createProduct(): Product
}
class Product {
<<interface>>
+operation()
}
class ConcreteProductA {
+operation()
}
class ConcreteProductB {
+operation()
}
Factory <|.. ConcreteFactoryA
Factory <|.. ConcreteFactoryB
ConcreteFactoryA --> ConcreteProductA
ConcreteFactoryB --> ConcreteProductB
Product <|.. ConcreteProductA
Product <|.. ConcreteProductB
对比总结表格:
| 特性 | 简单工厂 | 工厂方法 |
|---|---|---|
| 工厂角色 | 单个工厂类 | 工厂接口+多个实现 |
| 扩展性 | 添加新产品需修改工厂类 | 添加新产品只需新增工厂类 |
| 职责划分 | 工厂类集中创建逻辑 | 每个工厂负责单一产品 |
| 是否符合开闭原则 | 不符合 | 符合 |
| 适用场景 | 产品种类较少,变动不频繁 | 产品种类多、扩展频繁 |
4.1.2 扩展性与维护性比较
代码示例:简单工厂的扩展
// 产品接口
public interface Product {
void operation();
}
// 具体产品类
public class ProductA implements Product {
public void operation() {
System.out.println("ProductA operation");
}
}
public class ProductB implements Product {
public void operation() {
System.out.println("ProductB operation");
}
}
// 简单工厂类
public class SimpleFactory {
public Product createProduct(String type) {
if ("A".equals(type)) {
return new ProductA();
} else if ("B".equals(type)) {
return new ProductB();
} else {
throw new IllegalArgumentException("Unknown product type");
}
}
}
逐行分析:
-
createProduct方法根据传入的字符串参数决定返回哪种产品实例。 - 如果需要新增
ProductC,必须修改SimpleFactory类,添加新的if分支。 - 这种方式违反了开闭原则(对扩展开放,对修改关闭)。
工厂方法的扩展性示例:
// 工厂接口
public interface Factory {
Product createProduct();
}
// 具体工厂类
public class FactoryA implements Factory {
public Product createProduct() {
return new ProductA();
}
}
public class FactoryB implements Factory {
public Product createProduct() {
return new ProductB();
}
}
逐行分析:
- 每个具体工厂类负责创建一个产品。
- 新增产品只需新增一个工厂类,无需修改已有代码。
- 完全符合开闭原则,具有良好的扩展性。
4.1.3 适用场景的对比分析
| 场景 | 推荐使用 |
|---|---|
| 产品种类固定、数量少 | 简单工厂 |
| 需要频繁扩展新产品 | 工厂方法 |
| 团队协作、模块解耦 | 工厂方法 |
| 快速原型开发 | 简单工厂 |
工厂方法虽然结构稍复杂,但在大型项目、长期维护和团队协作中更具有优势。而简单工厂则适用于小型项目或原型阶段。
4.2 工厂方法与抽象工厂的对比
4.2.1 两者的结构与职责划分
工厂方法结构回顾
如前所述,工厂方法模式通过 接口定义工厂方法 ,由不同的具体工厂创建不同的产品。
抽象工厂结构
抽象工厂模式(Abstract Factory)用于创建 一组相关或相互依赖的产品族 。其结构通常包括:
- AbstractFactory :抽象工厂接口,定义创建产品族的方法
- ConcreteFactory :具体工厂,实现接口方法,创建一组产品
- AbstractProduct :抽象产品接口
- ProductA1、ProductA2… :同一产品族下的不同产品
mermaid流程图展示:
classDiagram
class AbstractFactory {
<<interface>>
+createProductA(): AbstractProductA
+createProductB(): AbstractProductB
}
class ConcreteFactory1 {
+createProductA(): ProductA1
+createProductB(): ProductB1
}
class ConcreteFactory2 {
+createProductA(): ProductA2
+createProductB(): ProductB2
}
AbstractFactory <|.. ConcreteFactory1
AbstractFactory <|.. ConcreteFactory2
class AbstractProductA {
<<interface>>
+operationA()
}
class ProductA1 {
+operationA()
}
class ProductA2 {
+operationA()
}
AbstractProductA <|.. ProductA1
AbstractProductA <|.. ProductA2
class AbstractProductB {
<<interface>>
+operationB()
}
class ProductB1 {
+operationB()
}
class ProductB2 {
+operationB()
}
AbstractProductB <|.. ProductB1
AbstractProductB <|.. ProductB2
对比表格:
| 特性 | 工厂方法 | 抽象工厂 |
|---|---|---|
| 创建对象 | 单个产品 | 产品族(多个产品) |
| 工厂接口 | 一个方法创建一个产品 | 多个方法创建多个产品 |
| 适用场景 | 单一产品扩展 | 相关产品族统一创建 |
| 是否支持产品等级结构 | 否 | 是 |
4.2.2 产品族与产品等级结构的管理
- 产品等级结构(Product Hierarchy) :同一产品的不同实现,如
Button接口下的WindowsButton和MacButton。 - 产品族(Product Family) :同一平台下的一组相关产品,如 Windows 下的
Button、TextBox、MenuBar。
抽象工厂特别适用于跨平台的 UI 框架设计,例如 Java 的 AWT 或跨平台应用开发框架。
示例代码:抽象工厂的实现
// 产品A接口
public interface Button {
void render();
}
// Windows 实现
public class WindowsButton implements Button {
public void render() {
System.out.println("Windows Button");
}
}
// Mac 实现
public class MacButton implements Button {
public void render() {
System.out.println("Mac Button");
}
}
// 产品B接口
public interface TextBox {
void render();
}
// Windows 实现
public class WindowsTextBox implements TextBox {
public void render() {
System.out.println("Windows TextBox");
}
}
// Mac 实现
public class MacTextBox implements TextBox {
public void render() {
System.out.println("Mac TextBox");
}
}
// 抽象工厂接口
public interface GUIFactory {
Button createButton();
TextBox createTextBox();
}
// Windows 工厂
public class WindowsFactory implements GUIFactory {
public Button createButton() {
return new WindowsButton();
}
public TextBox createTextBox() {
return new WindowsTextBox();
}
}
// Mac 工厂
public class MacFactory implements GUIFactory {
public Button createButton() {
return new MacButton();
}
public TextBox createTextBox() {
return new MacTextBox();
}
}
逐行分析:
-
GUIFactory接口定义了两个创建方法,分别用于创建按钮和文本框。 - 每个具体工厂实现了这两个方法,返回属于同一产品族的组件。
- 客户端无需关心具体组件的实现,只需使用工厂接口即可。
4.2.3 开闭原则的实现程度比较
| 模式 | 是否符合开闭原则 | 原因 |
|---|---|---|
| 工厂方法 | 符合 | 新增产品只需新增工厂类,无需修改已有类 |
| 抽象工厂 | 部分符合 | 新增产品族只需新增工厂类,但新增产品类型需修改抽象工厂接口 |
因此,在 新增产品族 的场景下,抽象工厂也符合开闭原则;但在 新增产品类型 时,则需要修改抽象工厂接口,这不符合开闭原则。
4.3 各类工厂模式的适用性总结
4.3.1 不同项目规模下的选择建议
| 项目规模 | 推荐模式 | 理由 |
|---|---|---|
| 小型项目 | 简单工厂 | 实现简单,易于快速开发 |
| 中型项目 | 工厂方法 | 扩展性强,适合产品种类多的场景 |
| 大型项目 | 抽象工厂 | 支持产品族创建,适用于复杂系统 |
4.3.2 面向未来扩展的设计策略
- 优先使用工厂方法 :满足开闭原则,适合大多数业务场景。
- 抽象工厂用于平台级抽象 :如 GUI 框架、数据库适配等。
- 组合使用 :工厂方法+策略模式、工厂+单例等,可构建更灵活的系统架构。
示例:工厂方法与策略模式的结合
public interface PaymentStrategy {
void pay(double amount);
}
public class CreditCardPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid " + amount + " via Credit Card");
}
}
public class PayPalPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid " + amount + " via PayPal");
}
}
public interface PaymentFactory {
PaymentStrategy createPayment();
}
public class CreditCardFactory implements PaymentFactory {
public PaymentStrategy createPayment() {
return new CreditCardPayment();
}
}
public class PayPalFactory implements PaymentFactory {
public PaymentStrategy createPayment() {
return new PayPalPayment();
}
}
逻辑分析:
- 工厂方法用于创建策略对象。
- 客户端通过工厂接口获取策略实例,无需了解具体实现。
- 这种方式既满足开闭原则,又具备良好的扩展性和可维护性。
本章通过结构对比、代码分析和适用场景讨论,系统地比较了三种主要工厂模式之间的异同。理解这些差异,有助于我们在实际项目中做出更加合理的设计决策,构建更高质量的软件系统。
5. 工厂模式在典型系统中的应用实践
工厂模式作为解耦对象创建与使用的经典设计模式,在实际系统开发中被广泛应用。本章将从三个典型应用场景出发:数据库连接池、跨平台GUI开发、以及Spring框架集成,深入剖析工厂模式在实际系统中的应用方式、设计逻辑及其带来的优势。通过具体案例和代码实现,我们将理解工厂模式如何在不同层级系统中提升扩展性、维护性与可测试性。
5.1 工厂模式在数据库连接池中的应用
数据库连接池是现代应用系统中提高数据库访问效率的重要机制。连接池通过复用数据库连接减少频繁建立和关闭连接的开销,而工厂模式则在连接池的实现中起到了解耦连接创建与使用的关键作用。
5.1.1 数据库连接池的基本原理
数据库连接池的核心在于“连接复用”。它通过预先创建多个数据库连接对象并缓存起来,当系统需要访问数据库时,从连接池中获取空闲连接;使用完成后归还连接,而不是关闭它。这种机制减少了建立连接的开销,提高了系统响应速度。
连接池的关键组件包括:
| 组件 | 功能说明 |
|---|---|
| 连接池管理器 | 负责连接的创建、分配、回收和销毁 |
| 连接工厂 | 负责创建数据库连接 |
| 连接对象 | 实际的数据库连接 |
5.1.2 使用工厂模式构建连接池
在连接池的设计中, 连接工厂(ConnectionFactory) 承担了创建连接的职责。通过工厂模式,我们可以灵活切换不同的数据库实现,例如从MySQL切换到PostgreSQL,只需修改工厂的实现类,而不影响连接池的其他部分。
以下是一个简单的连接工厂接口设计:
public interface ConnectionFactory {
Connection createConnection();
}
MySQL连接工厂实现如下:
public class MySQLConnectionFactory implements ConnectionFactory {
@Override
public Connection createConnection() {
try {
// 创建MySQL连接
return DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
} catch (SQLException e) {
throw new RuntimeException("Failed to create MySQL connection", e);
}
}
}
逻辑分析:
-
ConnectionFactory接口定义了创建连接的契约; -
MySQLConnectionFactory实现了具体的连接创建逻辑; - 连接池在获取连接时调用
createConnection()方法; - 这种设计使得连接池不依赖于具体数据库实现,符合开闭原则。
5.1.3 实际案例:基于工厂模式的连接池实现
下面是一个简化版的连接池实现,使用工厂模式来创建连接:
public class ConnectionPool {
private final Queue<Connection> pool;
private final ConnectionFactory factory;
private final int maxConnections;
public ConnectionPool(ConnectionFactory factory, int maxConnections) {
this.factory = factory;
this.maxConnections = maxConnections;
this.pool = new LinkedList<>();
initializeConnections();
}
private void initializeConnections() {
for (int i = 0; i < maxConnections; i++) {
pool.add(factory.createConnection());
}
}
public synchronized Connection getConnection() {
if (pool.isEmpty()) {
throw new RuntimeException("No available connections");
}
return pool.poll();
}
public synchronized void releaseConnection(Connection connection) {
pool.offer(connection);
}
}
逻辑分析:
-
ConnectionPool类使用工厂factory创建连接; - 初始化时预先创建
maxConnections个连接; - 每次调用
getConnection()从队列中取出一个连接; - 使用完后通过
releaseConnection()归还连接; - 工厂模式的引入使得连接池可以适应不同的数据库类型。
流程图展示连接池获取连接的逻辑:
graph TD
A[获取连接请求] --> B{连接池是否为空?}
B -->|是| C[抛出异常]
B -->|否| D[从队列中取出连接]
D --> E[返回连接]
5.2 工厂模式在跨平台GUI开发中的应用
在开发跨平台GUI应用时,一个常见的问题是不同操作系统下的界面组件实现不同。例如,Windows平台使用Win32 API创建按钮,而MacOS则使用Cocoa框架。此时, 抽象工厂模式 (Abstract Factory)成为解决该问题的理想方案。
5.2.1 GUI框架中的平台适配问题
跨平台GUI开发中面临的主要挑战是:
- 不同平台的控件实现不同;
- 控件外观和行为可能存在差异;
- 需要统一的接口进行调用。
抽象工厂模式允许我们定义一个创建控件族的接口,而每个具体工厂负责创建特定平台下的控件族。
5.2.2 工厂模式在跨平台控件创建中的使用
我们可以定义一个抽象工厂 UIFactory ,用于创建不同类型的UI组件:
public interface UIFactory {
Button createButton();
CheckBox createCheckBox();
}
然后为不同平台提供实现类,例如Windows平台:
public class WinUIFactory implements UIFactory {
@Override
public Button createButton() {
return new WinButton();
}
@Override
public CheckBox createCheckBox() {
return new WinCheckBox();
}
}
MacOS平台实现:
public class MacUIFactory implements UIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public CheckBox createCheckBox() {
return new MacCheckBox();
}
}
逻辑分析:
-
UIFactory接口定义了创建控件族的能力; - 每个具体工厂(如
WinUIFactory、MacUIFactory)负责创建特定平台下的控件; - 应用程序在运行时根据操作系统选择合适的工厂;
- 这样可以保证在不同平台下统一调用方式,同时使用平台相关的实现。
5.2.3 示例:基于抽象工厂的界面组件创建
下面是一个跨平台GUI创建的完整示例:
public class Application {
private final UIFactory factory;
private final Button button;
private final CheckBox checkBox;
public Application(UIFactory factory) {
this.factory = factory;
this.button = factory.createButton();
this.checkBox = factory.createCheckBox();
}
public void render() {
button.render();
checkBox.render();
}
}
运行示例:
public class Main {
public static void main(String[] args) {
UIFactory factory;
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
factory = new WinUIFactory();
} else if (os.contains("mac")) {
factory = new MacUIFactory();
} else {
throw new UnsupportedOperationException("Unsupported OS");
}
Application app = new Application(factory);
app.render();
}
}
逻辑分析:
-
Application类通过传入的UIFactory创建控件; -
Main类根据操作系统决定使用哪个工厂; -
render()方法统一调用控件的渲染方法; - 工厂模式的使用使得平台切换变得简单且透明。
控件创建流程图:
graph TD
A[应用程序启动] --> B[读取操作系统]
B --> C{操作系统类型?}
C -->|Windows| D[使用WinUIFactory]
C -->|MacOS| E[使用MacUIFactory]
D & E --> F[创建对应控件]
F --> G[调用render方法渲染界面]
5.3 工厂模式与Spring框架的集成
Spring框架是Java企业级开发中最流行的IoC容器,它在内部大量使用了工厂模式来管理Bean的创建过程。通过Spring工厂模式,开发者可以实现高度解耦、易于测试和维护的应用架构。
5.3.1 Spring中Bean的创建机制
Spring IoC容器负责管理Bean的生命周期,其核心机制包括:
- Bean定义(BeanDefinition);
- Bean工厂(BeanFactory);
- 应用上下文(ApplicationContext)。
Spring通过 BeanFactory 或 ApplicationContext 来创建Bean实例。默认情况下,Spring使用反射机制创建Bean,但也可以通过工厂方法自定义Bean的创建逻辑。
5.3.2 工厂模式在Spring IoC中的体现
在Spring中,工厂模式主要体现在以下两种方式:
- 静态工厂方法 :通过静态方法返回Bean实例;
- 实例工厂方法 :通过已有Bean实例的方法创建新Bean。
静态工厂方法示例:
public class MyServiceFactory {
public static MyService createService() {
return new MyServiceImpl();
}
}
Spring配置文件中配置:
<bean id="myService" class="com.example.MyServiceFactory" factory-method="createService"/>
实例工厂方法示例:
public class MyServiceFactory {
public MyService createService() {
return new MyServiceImpl();
}
}
Spring配置:
<bean id="factory" class="com.example.MyServiceFactory"/>
<bean id="myService" factory-bean="factory" factory-method="createService"/>
逻辑分析:
- Spring通过
factory-method指定工厂方法; - 通过工厂创建Bean,实现解耦;
- 工厂类可以被复用,增强系统的灵活性。
5.3.3 使用Spring工厂模式提升系统解耦能力
Spring通过工厂模式实现了高度解耦的系统结构。以下是一个典型的解耦示例:
public interface PaymentService {
void pay(double amount);
}
public class AlipayService implements PaymentService {
@Override
public void pay(double amount) {
System.out.println("支付 " + amount + " 元 via 支付宝");
}
}
public class PaymentServiceFactory {
public static PaymentService getPaymentService(String type) {
if ("alipay".equals(type)) {
return new AlipayService();
}
throw new IllegalArgumentException("Unsupported payment type");
}
}
Spring配置:
<bean id="paymentService" class="com.example.PaymentServiceFactory" factory-method="getPaymentService">
<constructor-arg value="alipay"/>
</bean>
逻辑分析:
-
PaymentServiceFactory负责创建支付服务; - Spring通过工厂方法注入Bean;
- 如果未来新增支付方式,只需修改工厂逻辑,无需改动调用代码;
- 此方式实现了业务逻辑与具体实现的完全解耦。
Spring工厂Bean创建流程图:
graph TD
A[Spring容器启动] --> B[加载Bean定义]
B --> C[发现factory-method配置]
C --> D[调用静态/实例工厂方法]
D --> E[创建Bean实例]
E --> F[注入到依赖对象中]
本章通过数据库连接池、跨平台GUI开发和Spring框架集成三个典型应用场景,系统性地阐述了工厂模式在实际系统中的应用方式。从简单工厂到抽象工厂,再到Spring的工厂Bean机制,展示了工厂模式在提升系统解耦、扩展性和可维护性方面的巨大价值。这些实践不仅验证了工厂模式的实用性,也为后续章节中工厂模式的最佳实践与优化策略提供了理论基础和实践依据。
6. 工厂模式的最佳实践与设计优化
6.1 工厂模式与开闭原则的结合
6.1.1 开闭原则的核心理念
开闭原则(Open-Closed Principle, OCP)是面向对象设计中最重要的原则之一,其核心思想是: 对扩展开放,对修改关闭 。这意味着一个软件实体(如类、模块、函数等)应当允许在不修改原有代码的前提下进行功能扩展。
6.1.2 工厂模式如何支持开闭原则
工厂模式通过将对象的创建过程封装到工厂类中,使得客户端代码与具体类的依赖关系被解除。当需要新增一个产品类时,只需新增对应的工厂类和产品类,而无需修改已有代码,从而实现对扩展开放、对修改关闭。
例如,在简单工厂模式中,如果我们要添加一个新的产品类 ProductC ,只需在工厂类的 createProduct 方法中增加一个判断分支。然而,这种做法在一定程度上违背了开闭原则,因为需要修改工厂类。而使用工厂方法模式,则可以为每个产品创建对应的工厂类,这样在新增产品时,只需新增工厂类,无需修改已有代码。
6.1.3 实践案例:通过工厂扩展实现零修改新增功能
以下是一个使用工厂方法模式实现开闭原则的示例:
// 产品接口
public interface Product {
void use();
}
// 具体产品A
public class ProductA implements Product {
public void use() {
System.out.println("Using Product A");
}
}
// 具体产品B
public class ProductB implements Product {
public void use() {
System.out.println("Using Product B");
}
}
// 工厂接口
public interface ProductFactory {
Product createProduct();
}
// 工厂方法实现A
public class ProductAFactory implements ProductFactory {
public Product createProduct() {
return new ProductA();
}
}
// 工厂方法实现B
public class ProductBFactory implements ProductFactory {
public Product createProduct() {
return new ProductB();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ProductFactory factory = new ProductAFactory();
Product product = factory.createProduct();
product.use();
}
}
代码说明:
-
Product是产品的抽象接口。 -
ProductA和ProductB是具体产品类。 -
ProductFactory是工厂接口。 -
ProductAFactory和ProductBFactory是具体的工厂类。 - 客户端通过调用工厂类的
createProduct()方法来获取产品实例,而无需关心具体实现。
扩展方式:
如果需要新增一个 ProductC ,只需创建 ProductC 类和对应的 ProductCFactory ,而无需修改现有类,完全符合开闭原则。
6.2 工厂模式在项目开发中的最佳实践
6.2.1 设计阶段的模式选择策略
在项目设计阶段选择工厂模式时,应根据以下因素进行决策:
| 因素 | 简单工厂 | 工厂方法 | 抽象工厂 |
|---|---|---|---|
| 扩展性 | 低 | 高 | 非常高 |
| 维护性 | 一般 | 高 | 高 |
| 适用场景 | 产品种类少、变化不频繁 | 产品种类多、扩展频繁 | 多产品族、跨平台开发 |
| 实现复杂度 | 低 | 中 | 高 |
- 简单工厂 适用于小型项目或产品种类固定的情况。
- 工厂方法 适用于需要频繁扩展产品种类的中大型项目。
- 抽象工厂 适用于跨平台、多产品族的应用场景。
6.2.2 编码阶段的工厂结构优化
在编码阶段,可以采取以下优化策略:
- 使用枚举或配置文件驱动工厂 :避免硬编码,提升灵活性。
- 引入缓存机制 :对创建成本高的对象进行缓存,提高性能。
- 统一命名规范 :工厂类和产品类采用一致的命名方式,便于维护。
- 分离工厂接口与实现 :增强扩展性和测试性。
示例:使用枚举驱动的工厂:
public enum ProductType {
A, B, C
}
public class ProductFactory {
public static Product createProduct(ProductType type) {
switch (type) {
case A: return new ProductA();
case B: return new ProductB();
case C: return new ProductC();
default: throw new IllegalArgumentException("Unknown product type");
}
}
}
6.2.3 维护阶段的工厂模式重构建议
在系统维护阶段,如果发现以下问题,应考虑重构工厂模式:
- 工厂类过于庞大 :说明产品种类过多,应考虑使用工厂方法或抽象工厂进行拆分。
- 频繁修改工厂逻辑 :说明当前模式不支持开闭原则,应升级为工厂方法模式。
- 工厂与业务逻辑耦合 :应将工厂逻辑抽离,独立封装,提升解耦能力。
6.3 工厂模式与其他设计模式的结合
6.3.1 工厂模式与单例模式的结合
应用场景: 当需要创建的对象在整个系统中只能存在一个实例时,可以将工厂模式与单例模式结合使用。
示例:
public class SingletonProductFactory {
private static volatile SingletonProductFactory instance;
private SingletonProductFactory() {}
public static SingletonProductFactory getInstance() {
if (instance == null) {
synchronized (SingletonProductFactory.class) {
if (instance == null) {
instance = new SingletonProductFactory();
}
}
}
return instance;
}
public Product createProduct() {
return new ProductA(); // 或根据需求返回不同的产品
}
}
优势:
- 保证工厂类的唯一性,避免重复创建。
- 提升系统资源利用率和性能。
6.3.2 工厂模式与策略模式的融合应用
应用场景: 在需要根据上下文动态切换不同算法或行为时,可以使用策略模式;而策略对象的创建则可以使用工厂模式进行封装。
示例结构图(Mermaid):
graph TD
A[Context] -->|uses| B(StrategyFactory)
B -->|creates| C[StrategyA]
B -->|creates| D[StrategyB]
C -->|implements| E[Strategy]
D -->|implements| E
代码片段:
public interface Strategy {
void execute();
}
public class StrategyA implements Strategy {
public void execute() { System.out.println("Executing Strategy A"); }
}
public class StrategyB implements Strategy {
public void execute() { System.out.println("Executing Strategy B"); }
}
public class StrategyFactory {
public static Strategy createStrategy(String type) {
switch (type) {
case "A": return new StrategyA();
case "B": return new StrategyB();
default: throw new IllegalArgumentException("Unknown strategy");
}
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
}
优势:
- 工厂模式负责创建策略对象,策略模式负责行为的动态切换。
- 提升系统的灵活性和可维护性。
6.3.3 复合使用模式带来的系统架构提升
将工厂模式与多种设计模式(如模板方法、代理、观察者等)复合使用,能够有效提升系统的解耦性、扩展性和可测试性。例如:
- 工厂 + 模板方法 :用于创建标准化流程的实例。
- 工厂 + 代理 :用于创建具有访问控制的对象。
- 工厂 + 观察者 :用于创建可动态注册监听的对象。
总结:
工厂模式作为解耦利器,其最佳实践不仅在于正确使用,更在于与其他设计模式的合理结合,从而构建出高内聚、低耦合、可扩展的系统架构。
简介:工厂模式是Java中一种重要的创建型设计模式,旨在将对象的创建过程封装,降低代码耦合度,提升灵活性。主要分为简单工厂、工厂方法和抽象工厂三种类型,分别适用于不同复杂度的业务场景。本案例通过详细讲解三种工厂模式的实现原理与使用场景,结合数据库连接池、GUI组件创建等实际应用,帮助开发者掌握如何在项目中灵活运用工厂模式,提升代码的可维护性与可扩展性。
1586

被折叠的 条评论
为什么被折叠?



