工厂模式
工厂模式是创建型模式之一,通过工厂类创建对象,而不直接使用new关键字。工厂模式解耦对象的创建和使用,提高代码的可维护性和扩展性。
📋 模式概述
定义: 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
适用场景:
- 需要根据条件动态创建对象
- 对象的创建过程复杂
- 需要解耦对象的创建和使用
- 需要统一管理对象的创建
🎯 一、项目案例:支付方式工厂
1.1 问题场景
在电商支付系统中,用户可以选择多种支付方式(支付宝、微信、银行卡等)。如果直接使用if-else创建不同的支付对象,会导致:
- 代码耦合度高
- 新增支付方式需要修改现有代码
- 难以维护和扩展
1.2 工厂模式解决方案
项目背景: 电商支付系统,支持多种支付方式
步骤1:定义支付接口
java
/**
* 支付接口
* 项目案例:电商支付系统
*/
public interface Payment {
/**
* 支付
* @param amount 支付金额
* @return 支付结果
*/
PaymentResult pay(BigDecimal amount);
/**
* 退款
* @param orderId 订单号
* @param amount 退款金额
* @return 退款结果
*/
RefundResult refund(String orderId, BigDecimal amount);
/**
* 查询支付状态
* @param orderId 订单号
* @return 支付状态
*/
PaymentStatus queryStatus(String orderId);
}步骤2:实现具体的支付方式
java
/**
* 支付宝支付实现
*/
public class AlipayPayment implements Payment {
private AlipayClient alipayClient;
public AlipayPayment(AlipayClient alipayClient) {
this.alipayClient = alipayClient;
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("使用支付宝支付: " + amount);
// 调用支付宝SDK进行支付
AlipayTradePayRequest request = new AlipayTradePayRequest();
request.setBizContent("{" +
" \"out_trade_no\":\"" + generateTradeNo() + "\"," +
" \"total_amount\":\"" + amount + "\"," +
" \"subject\":\"商品购买\"" +
"}");
try {
AlipayTradePayResponse response = alipayClient.execute(request);
return new PaymentResult(response.isSuccess(), response.getTradeNo());
} catch (Exception e) {
return new PaymentResult(false, e.getMessage());
}
}
@Override
public RefundResult refund(String orderId, BigDecimal amount) {
// 支付宝退款逻辑
System.out.println("支付宝退款: " + orderId + ", 金额: " + amount);
return new RefundResult(true, "退款成功");
}
@Override
public PaymentStatus queryStatus(String orderId) {
// 查询支付宝支付状态
return PaymentStatus.SUCCESS;
}
private String generateTradeNo() {
return "ALIPAY_" + System.currentTimeMillis();
}
}java
/**
* 微信支付实现
*/
public class WechatPayment implements Payment {
private WxPayService wxPayService;
public WechatPayment(WxPayService wxPayService) {
this.wxPayService = wxPayService;
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("使用微信支付: " + amount);
// 调用微信支付SDK
WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
request.setTotalFee(amount.multiply(new BigDecimal("100")).intValue());
request.setOutTradeNo(generateTradeNo());
request.setBody("商品购买");
try {
WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(request);
return new PaymentResult(true, result.getPrepayId());
} catch (Exception e) {
return new PaymentResult(false, e.getMessage());
}
}
@Override
public RefundResult refund(String orderId, BigDecimal amount) {
// 微信退款逻辑
System.out.println("微信退款: " + orderId + ", 金额: " + amount);
return new RefundResult(true, "退款成功");
}
@Override
public PaymentStatus queryStatus(String orderId) {
// 查询微信支付状态
return PaymentStatus.SUCCESS;
}
private String generateTradeNo() {
return "WECHAT_" + System.currentTimeMillis();
}
}java
/**
* 银行卡支付实现
*/
public class BankCardPayment implements Payment {
private BankCardService bankCardService;
public BankCardPayment(BankCardService bankCardService) {
this.bankCardService = bankCardService;
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("使用银行卡支付: " + amount);
// 调用银行接口进行支付
return bankCardService.processPayment(amount);
}
@Override
public RefundResult refund(String orderId, BigDecimal amount) {
// 银行卡退款逻辑
System.out.println("银行卡退款: " + orderId + ", 金额: " + amount);
return new RefundResult(true, "退款成功");
}
@Override
public PaymentStatus queryStatus(String orderId) {
// 查询银行卡支付状态
return PaymentStatus.SUCCESS;
}
}步骤3:创建支付工厂
java
/**
* 支付工厂 - 简单工厂模式
* 项目案例:电商支付系统
*/
public class PaymentFactory {
// 支付方式枚举
public enum PaymentType {
ALIPAY, WECHAT, BANK_CARD
}
/**
* 创建支付对象
* @param paymentType 支付类型
* @return 支付对象
*/
public static Payment createPayment(PaymentType paymentType) {
switch (paymentType) {
case ALIPAY:
return new AlipayPayment(createAlipayClient());
case WECHAT:
return new WechatPayment(createWxPayService());
case BANK_CARD:
return new BankCardPayment(createBankCardService());
default:
throw new IllegalArgumentException("不支持的支付方式: " + paymentType);
}
}
/**
* 根据字符串创建支付对象
*/
public static Payment createPayment(String paymentType) {
try {
PaymentType type = PaymentType.valueOf(paymentType.toUpperCase());
return createPayment(type);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("不支持的支付方式: " + paymentType);
}
}
private static AlipayClient createAlipayClient() {
// 初始化支付宝客户端
return new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
"app_id",
"private_key",
"json",
"UTF-8",
"alipay_public_key",
"RSA2"
);
}
private static WxPayService createWxPayService() {
// 初始化微信支付服务
WxPayConfig config = new WxPayConfig();
config.setAppId("app_id");
config.setMchId("mch_id");
config.setMchKey("mch_key");
return new WxPayServiceImpl(config);
}
private static BankCardService createBankCardService() {
// 初始化银行卡服务
return new BankCardServiceImpl();
}
}步骤4:使用工厂创建支付对象
java
/**
* 订单服务 - 使用支付工厂
* 项目案例:电商订单支付
*/
@Service
public class OrderService {
/**
* 处理订单支付
*/
public void processPayment(Order order, String paymentType) {
// 使用工厂创建支付对象
Payment payment = PaymentFactory.createPayment(paymentType);
// 执行支付
PaymentResult result = payment.pay(order.getTotalAmount());
if (result.isSuccess()) {
// 更新订单状态
order.setStatus(OrderStatus.PAID);
order.setPaymentTradeNo(result.getTradeNo());
orderRepository.save(order);
// 发送支付成功通知
notificationService.sendPaymentSuccessNotification(order);
} else {
// 处理支付失败
handlePaymentFailure(order, result.getErrorMessage());
}
}
/**
* 处理订单退款
*/
public void processRefund(Order order) {
// 根据订单的支付方式创建对应的支付对象
Payment payment = PaymentFactory.createPayment(order.getPaymentType());
// 执行退款
RefundResult result = payment.refund(order.getOrderId(), order.getTotalAmount());
if (result.isSuccess()) {
order.setStatus(OrderStatus.REFUNDED);
orderRepository.save(order);
}
}
}好处:
- 解耦: 订单服务不需要知道具体的支付实现类
- 易扩展: 新增支付方式只需添加新的实现类和修改工厂
- 统一管理: 支付对象的创建逻辑集中在工厂类中
🎯 二、工厂方法模式
2.1 工厂方法模式定义
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。
2.2 项目案例:数据库连接工厂
项目背景: 微服务系统需要支持多种数据库(MySQL、PostgreSQL、Oracle)
java
/**
* 数据库连接工厂接口
*/
public interface DatabaseConnectionFactory {
Connection createConnection();
DatabaseConnectionPool createConnectionPool();
}java
/**
* MySQL连接工厂
*/
public class MySQLConnectionFactory implements DatabaseConnectionFactory {
private String host;
private int port;
private String database;
private String username;
private String password;
public MySQLConnectionFactory(String host, int port, String database,
String username, String password) {
this.host = host;
this.port = port;
this.database = database;
this.username = username;
this.password = password;
}
@Override
public Connection createConnection() throws SQLException {
String url = "jdbc:mysql://" + host + ":" + port + "/" + database;
return DriverManager.getConnection(url, username, password);
}
@Override
public DatabaseConnectionPool createConnectionPool() {
return new MySQLConnectionPool(host, port, database, username, password);
}
}java
/**
* PostgreSQL连接工厂
*/
public class PostgreSQLConnectionFactory implements DatabaseConnectionFactory {
private String host;
private int port;
private String database;
private String username;
private String password;
public PostgreSQLConnectionFactory(String host, int port, String database,
String username, String password) {
this.host = host;
this.port = port;
this.database = database;
this.username = username;
this.password = password;
}
@Override
public Connection createConnection() throws SQLException {
String url = "jdbc:postgresql://" + host + ":" + port + "/" + database;
return DriverManager.getConnection(url, username, password);
}
@Override
public DatabaseConnectionPool createConnectionPool() {
return new PostgreSQLConnectionPool(host, port, database, username, password);
}
}java
/**
* 数据访问层 - 使用工厂方法
*/
public class UserRepository {
private DatabaseConnectionFactory connectionFactory;
public UserRepository(DatabaseConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public User findById(Long id) {
try (Connection conn = connectionFactory.createConnection()) {
// 查询用户逻辑
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setLong(1, id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return mapToUser(rs);
}
return null;
} catch (SQLException e) {
throw new RuntimeException("查询用户失败", e);
}
}
private User mapToUser(ResultSet rs) throws SQLException {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
}🎯 三、抽象工厂模式
3.1 抽象工厂模式定义
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
3.2 项目案例:UI组件工厂
项目背景: 跨平台UI系统,支持Windows和Mac两种风格
java
/**
* UI组件工厂接口
*/
public interface UIFactory {
Button createButton();
TextField createTextField();
Dialog createDialog();
}java
/**
* Windows风格UI工厂
*/
public class WindowsUIFactory implements UIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextField createTextField() {
return new WindowsTextField();
}
@Override
public Dialog createDialog() {
return new WindowsDialog();
}
}java
/**
* Mac风格UI工厂
*/
public class MacUIFactory implements UIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextField createTextField() {
return new MacTextField();
}
@Override
public Dialog createDialog() {
return new MacDialog();
}
}📖 三种工厂模式对比
| 模式 | 特点 | 适用场景 |
|---|---|---|
| 简单工厂 | 一个工厂类创建所有对象 | 对象类型较少,创建逻辑简单 |
| 工厂方法 | 每个产品对应一个工厂 | 需要扩展产品类型 |
| 抽象工厂 | 创建产品族 | 需要创建一系列相关的产品 |
✅ 学习检查清单
- [ ] 已理解简单工厂模式
- [ ] 已理解工厂方法模式
- [ ] 已理解抽象工厂模式
- [ ] 已在项目中应用工厂模式
- [ ] 已了解三种工厂模式的区别和适用场景