文章目录
-
- 什么是简单工厂模式?
- 核心思想
- 模式结构
- 代码示例
-
- 场景描述
- [1. 定义抽象产品接口](#1. 定义抽象产品接口)
- [2. 实现具体产品类](#2. 实现具体产品类)
- [3. 创建工厂类](#3. 创建工厂类)
- [4. 客户端使用示例](#4. 客户端使用示例)
- [5. 进阶示例:可配置的工厂](#5. 进阶示例:可配置的工厂)
- 简单工厂模式的优点
-
- [1. 封装创建逻辑](#1. 封装创建逻辑)
- [2. 代码复用](#2. 代码复用)
- [3. 易于维护](#3. 易于维护)
- 简单工厂模式的缺点
-
- [1. 违反开闭原则](#1. 违反开闭原则)
- [2. 工厂类职责过重](#2. 工厂类职责过重)
- 适用场景
- 最佳实践
-
- [1. 使用枚举增强类型安全](#1. 使用枚举增强类型安全)
- [2. 添加异常处理机制](#2. 添加异常处理机制)
- [3. 考虑使用配置文件](#3. 考虑使用配置文件)
- 总结
什么是简单工厂模式?
简单工厂模式(Simple Factory Pattern)是创建型设计模式中最简单的一种,它提供了一个专门的工厂类来负责创建对象的实例,而客户端无需关心具体的创建细节。这种模式通过将对象的创建和使用分离,实现了代码的解耦和复用。
核心思想
简单工厂模式的核心思想是:将对象的创建过程封装在一个工厂类中,客户端只需要知道传入工厂类的参数,而不需要关心对象的具体创建过程。
模式结构
简单工厂模式包含三个主要角色:
- 工厂类(Factory):负责创建具体产品对象的核心类
- 抽象产品(Product):定义产品的公共接口
- 具体产品(Concrete Product):实现抽象产品接口的具体类
代码示例
让我们通过一个完整的示例来深入理解简单工厂模式。
场景描述
假设我们正在开发一个支付系统,需要支持多种支付方式:支付宝、微信支付、银联支付等。使用简单工厂模式可以优雅地管理这些支付方式的创建。
1. 定义抽象产品接口
java
/**
* 支付接口 - 抽象产品角色
*/
public interface Payment {
/**
* 支付操作
* @param amount 支付金额
* @return 支付结果
*/
boolean pay(double amount);
/**
* 获取支付方式名称
* @return 支付方式名称
*/
String getPaymentMethod();
}
2. 实现具体产品类
java
/**
* 支付宝支付 - 具体产品角色
*/
public class AlipayPayment implements Payment {
@Override
public boolean pay(double amount) {
System.out.println("使用支付宝支付:" + amount + "元");
// 模拟支付处理逻辑
System.out.println("支付宝支付处理中...");
System.out.println("支付成功!");
return true;
}
@Override
public String getPaymentMethod() {
return "支付宝支付";
}
}
/**
* 微信支付 - 具体产品角色
*/
public class WechatPayment implements Payment {
@Override
public boolean pay(double amount) {
System.out.println("使用微信支付:" + amount + "元");
// 模拟支付处理逻辑
System.out.println("微信支付处理中...");
System.out.println("支付成功!");
return true;
}
@Override
public String getPaymentMethod() {
return "微信支付";
}
}
/**
* 银联支付 - 具体产品角色
*/
public class UnionPayment implements Payment {
@Override
public boolean pay(double amount) {
System.out.println("使用银联支付:" + amount + "元");
// 模拟支付处理逻辑
System.out.println("银联支付处理中...");
System.out.println("支付成功!");
return true;
}
@Override
public String getPaymentMethod() {
return "银联支付";
}
}
3. 创建工厂类
java
/**
* 支付工厂类 - 工厂角色
*/
public class PaymentFactory {
/**
* 创建支付对象
* @param paymentType 支付类型
* @return 支付对象
* @throws IllegalArgumentException 当支付类型不支持时抛出异常
*/
public static Payment createPayment(String paymentType) {
if (paymentType == null || paymentType.isEmpty()) {
throw new IllegalArgumentException("支付类型不能为空");
}
switch (paymentType.toLowerCase()) {
case "alipay":
return new AlipayPayment();
case "wechat":
return new WechatPayment();
case "union":
return new UnionPayment();
default:
throw new IllegalArgumentException("不支持的支付类型: " + paymentType);
}
}
/**
* 使用枚举方式创建支付对象(更安全的方式)
* @param paymentType 支付类型枚举
* @return 支付对象
*/
public static Payment createPayment(PaymentType paymentType) {
if (paymentType == null) {
throw new IllegalArgumentException("支付类型不能为空");
}
switch (paymentType) {
case ALIPAY:
return new AlipayPayment();
case WECHAT:
return new WechatPayment();
case UNION:
return new UnionPayment();
default:
throw new IllegalArgumentException("不支持的支付类型: " + paymentType);
}
}
}
/**
* 支付类型枚举
*/
public enum PaymentType {
ALIPAY, WECHAT, UNION
}
4. 客户端使用示例
java
/**
* 客户端代码 - 使用简单工厂模式
*/
public class Client {
public static void main(String[] args) {
// 示例1:使用字符串参数创建支付对象
System.out.println("=== 使用字符串参数创建支付对象 ===");
useStringParameter();
System.out.println("\n=== 使用枚举参数创建支付对象 ===");
// 示例2:使用枚举参数创建支付对象(推荐方式)
useEnumParameter();
System.out.println("\n=== 错误处理示例 ===");
// 示例3:错误处理
handleErrorCases();
}
private static void useStringParameter() {
try {
Payment alipay = PaymentFactory.createPayment("alipay");
alipay.pay(100.0);
System.out.println("支付方式:" + alipay.getPaymentMethod());
Payment wechat = PaymentFactory.createPayment("wechat");
wechat.pay(200.0);
System.out.println("支付方式:" + wechat.getPaymentMethod());
} catch (Exception e) {
System.err.println("支付创建失败: " + e.getMessage());
}
}
private static void useEnumParameter() {
try {
Payment unionPay = PaymentFactory.createPayment(PaymentType.UNION);
unionPay.pay(150.0);
System.out.println("支付方式:" + unionPay.getPaymentMethod());
} catch (Exception e) {
System.err.println("支付创建失败: " + e.getMessage());
}
}
private static void handleErrorCases() {
// 测试异常情况
try {
PaymentFactory.createPayment("");
} catch (IllegalArgumentException e) {
System.err.println("捕获异常: " + e.getMessage());
}
try {
PaymentFactory.createPayment("invalid");
} catch (IllegalArgumentException e) {
System.err.println("捕获异常: " + e.getMessage());
}
}
}
5. 进阶示例:可配置的工厂
java
/**
* 可配置的支付工厂 - 支持从配置文件加载映射关系
*/
public class ConfigurablePaymentFactory {
private static Map<String, Class<? extends Payment>> paymentMap = new HashMap<>();
static {
// 初始化默认映射
paymentMap.put("alipay", AlipayPayment.class);
paymentMap.put("wechat", WechatPayment.class);
paymentMap.put("union", UnionPayment.class);
}
/**
* 注册新的支付类型
* @param type 支付类型标识
* @param paymentClass 支付类
*/
public static void registerPayment(String type, Class<? extends Payment> paymentClass) {
paymentMap.put(type, paymentClass);
}
/**
* 创建支付对象
* @param type 支付类型
* @return 支付对象
*/
public static Payment createPayment(String type) {
if (!paymentMap.containsKey(type)) {
throw new IllegalArgumentException("不支持的支付类型: " + type);
}
try {
return paymentMap.get(type).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("创建支付对象失败", e);
}
}
}
简单工厂模式的优点
1. 封装创建逻辑
java
// 客户端代码简洁明了,无需了解具体创建细节
Payment payment = PaymentFactory.createPayment("alipay");
payment.pay(100.0);
2. 代码复用
java
// 多个地方使用相同的创建逻辑
public class OrderService {
public void processOrder(String paymentType, double amount) {
Payment payment = PaymentFactory.createPayment(paymentType);
payment.pay(amount);
// 其他订单处理逻辑...
}
}
public class RefundService {
public void processRefund(String paymentType, double amount) {
Payment payment = PaymentFactory.createPayment(paymentType);
// 退款处理逻辑...
}
}
3. 易于维护
当需要添加新的支付方式时,只需要修改工厂类,客户端代码无需改动。
简单工厂模式的缺点
1. 违反开闭原则
java
// 添加新的支付方式需要修改工厂类
public static Payment createPayment(String paymentType) {
switch (paymentType.toLowerCase()) {
case "alipay":
return new AlipayPayment();
case "wechat":
return new WechatPayment();
case "union":
return new UnionPayment();
// 新增支付方式需要修改这里
case "newpayment":
return new NewPayment(); // 需要修改源代码
default:
throw new IllegalArgumentException("不支持的支付类型: " + paymentType);
}
}
2. 工厂类职责过重
当产品类型很多时,工厂类的代码会变得臃肿。
适用场景
- 对象创建逻辑相对简单:不需要复杂的创建过程
- 客户端不关心具体实现:只需要知道类型标识即可
- 产品类型数量有限:不会频繁添加新产品
- 需要统一管理对象创建:集中化的创建逻辑
最佳实践
1. 使用枚举增强类型安全
java
// 推荐:使用枚举避免字符串硬编码
Payment payment = PaymentFactory.createPayment(PaymentType.ALIPAY);
2. 添加异常处理机制
java
public static Payment createPayment(PaymentType paymentType) {
if (paymentType == null) {
throw new IllegalArgumentException("支付类型不能为空");
}
// ... 创建逻辑
}
3. 考虑使用配置文件
java
// 通过配置文件管理类型映射,提高灵活性
Properties props = new Properties();
// 加载配置...
String className = props.getProperty(paymentType);
总结
简单工厂模式虽然简单,但在实际开发中非常实用。它通过将对象的创建和使用分离,提高了代码的灵活性和可维护性。然而,我们也需要认识到它的局限性,特别是在需要频繁扩展的场景下。
关键要点:
- 简单工厂模式适用于创建逻辑不复杂的场景
- 通过工厂类封装对象创建细节
- 客户端与具体产品类解耦
- 注意违反开闭原则的问题
- 合理使用枚举和异常处理提高代码质量
掌握简单工厂模式是学习更复杂工厂模式的基础,理解其思想对于编写高质量的面向对象代码具有重要意义。