工厂模式
定义
工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
核心思想
- 封装创建逻辑:将对象的创建过程封装在工厂类中
- 解耦客户端:客户端不需要知道具体对象的创建细节
- 统一管理:所有对象的创建都通过工厂统一管理
- 支持扩展:新增产品类型时,只需要扩展工厂,不需要修改现有代码
结构
角色组成
- Product(抽象产品):定义产品的公共接口
- ConcreteProduct(具体产品):实现抽象产品接口的具体类
- Factory(工厂):负责创建产品的工厂类
- Client(客户端):使用工厂创建产品的客户端
类图
┌─────────────────┐ ┌──────────────────┐
│ Client │ │ Factory │
├─────────────────┤ ├──────────────────┤
│ │───▶│ + createProduct()│
└─────────────────┘ └──────────────────┘
│
▼
┌──────────────────┐
│ Product │
├──────────────────┤
│ + operation() │
└──────────────────┘
▲
│
┌─────────────────────────────────────────┐
│ │
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ ConcreteProductA │ │ ConcreteProductB │ │ ConcreteProductC │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ + operation() │ │ + operation() │ │ + operation() │
└──────────────────┘ └──────────────────┘ └──────────────────┘
工厂模式类型
1. 简单工厂模式(Simple Factory)
电商系统中的商品类型管理,需要根据商品类型创建不同的商品对象。
抽象产品接口
public interface Product {
String getProductName();
BigDecimal getPrice();
String getDescription();
}
具体产品类
// 电子产品
@Component
public class ElectronicProduct implements Product {
private String name;
private BigDecimal price;
private String brand;
public ElectronicProduct(String name, BigDecimal price, String brand) {
this.name = name;
this.price = price;
this.brand = brand;
}
@Override
public String getProductName() {
return name;
}
@Override
public BigDecimal getPrice() {
return price;
}
@Override
public String getDescription() {
return "电子产品 - " + brand + " " + name;
}
}
// 服装产品
@Component
public class ClothingProduct implements Product {
private String name;
private BigDecimal price;
private String size;
public ClothingProduct(String name, BigDecimal price, String size) {
this.name = name;
this.price = price;
this.size = size;
}
@Override
public String getProductName() {
return name;
}
@Override
public BigDecimal getPrice() {
return price;
}
@Override
public String getDescription() {
return "服装产品 - " + name + " (尺码: " + size + ")";
}
}
// 食品产品
@Component
public class FoodProduct implements Product {
private String name;
private BigDecimal price;
private LocalDate expiryDate;
public FoodProduct(String name, BigDecimal price, LocalDate expiryDate) {
this.name = name;
this.price = price;
this.expiryDate = expiryDate;
}
@Override
public String getProductName() {
return name;
}
@Override
public BigDecimal getPrice() {
return price;
}
@Override
public String getDescription() {
return "食品产品 - " + name + " (过期时间: " + expiryDate + ")";
}
}
简单工厂类
@Service
public class ProductFactory {
public Product createProduct(String productType, String name, BigDecimal price, Map<String, Object> attributes) {
switch (productType.toLowerCase()) {
case "electronic":
String brand = (String) attributes.get("brand");
return new ElectronicProduct(name, price, brand);
case "clothing":
String size = (String) attributes.get("size");
return new ClothingProduct(name, price, size);
case "food":
LocalDate expiryDate = (LocalDate) attributes.get("expiryDate");
return new FoodProduct(name, price, expiryDate);
default:
throw new IllegalArgumentException("未知的商品类型: " + productType);
}
}
}
客户端使用
@RestController
@RequestMapping("/products")
public class ProductController {
@Autowired
private ProductFactory productFactory;
@PostMapping("/create")
public ResponseEntity<String> createProduct(@RequestBody ProductRequest request) {
try {
Product product = productFactory.createProduct(
request.getType(),
request.getName(),
request.getPrice(),
request.getAttributes()
);
return ResponseEntity.ok("商品创建成功: " + product.getDescription());
} catch (Exception e) {
return ResponseEntity.badRequest().body("商品创建失败: " + e.getMessage());
}
}
}
// 请求DTO
public class ProductRequest {
private String type;
private String name;
private BigDecimal price;
private Map<String, Object> attributes;
// getters and setters
}
2. 工厂方法模式(Factory Method)
支付系统中的不同支付方式处理,每种支付方式需要不同的处理逻辑。
抽象产品接口
public interface PaymentProcessor {
PaymentResult process(PaymentRequest request);
boolean supports(String paymentType);
}
具体产品类
// 支付宝支付处理器
@Component
public class AlipayProcessor implements PaymentProcessor {
@Override
public PaymentResult process(PaymentRequest request) {
// 模拟支付宝支付处理逻辑
System.out.println("处理支付宝支付: " + request.getAmount());
// 调用支付宝API
boolean success = callAlipayAPI(request);
return PaymentResult.builder()
.success(success)
.transactionId(success ? generateTransactionId() : null)
.message(success ? "支付宝支付成功" : "支付宝支付失败")
.build();
}
@Override
public boolean supports(String paymentType) {
return "alipay".equalsIgnoreCase(paymentType);
}
private boolean callAlipayAPI(PaymentRequest request) {
// 模拟支付宝API调用
return Math.random() > 0.1; // 90%成功率
}
private String generateTransactionId() {
return "ALI" + System.currentTimeMillis();
}
}
// 微信支付处理器
@Component
public class WechatPayProcessor implements PaymentProcessor {
@Override
public PaymentResult process(PaymentRequest request) {
// 模拟微信支付处理逻辑
System.out.println("处理微信支付: " + request.getAmount());
// 调用微信支付API
boolean success = callWechatPayAPI(request);
return PaymentResult.builder()
.success(success)
.transactionId(success ? generateTransactionId() : null)
.message(success ? "微信支付成功" : "微信支付失败")
.build();
}
@Override
public boolean supports(String paymentType) {
return "wechat".equalsIgnoreCase(paymentType);
}
private boolean callWechatPayAPI(PaymentRequest request) {
// 模拟微信支付API调用
return Math.random() > 0.1; // 90%成功率
}
private String generateTransactionId() {
return "WX" + System.currentTimeMillis();
}
}
// 银行卡支付处理器
@Component
public class BankCardProcessor implements PaymentProcessor {
@Override
public PaymentResult process(PaymentRequest request) {
// 模拟银行卡支付处理逻辑
System.out.println("处理银行卡支付: " + request.getAmount());
// 调用银行API
boolean success = callBankAPI(request);
return PaymentResult.builder()
.success(success)
.transactionId(success ? generateTransactionId() : null)
.message(success ? "银行卡支付成功" : "银行卡支付失败")
.build();
}
@Override
public boolean supports(String paymentType) {
return "bankcard".equalsIgnoreCase(paymentType);
}
private boolean callBankAPI(PaymentRequest request) {
// 模拟银行API调用
return Math.random() > 0.1; // 90%成功率
}
private String generateTransactionId() {
return "BANK" + System.currentTimeMillis();
}
}
抽象工厂接口
public interface PaymentProcessorFactory {
PaymentProcessor createProcessor(String paymentType);
}
具体工厂类
@Service
public class PaymentProcessorFactoryImpl implements PaymentProcessorFactory {
private final List<PaymentProcessor> processors;
@Autowired
public PaymentProcessorFactoryImpl(List<PaymentProcessor> processors) {
this.processors = processors;
}
@Override
public PaymentProcessor createProcessor(String paymentType) {
return processors.stream()
.filter(processor -> processor.supports(paymentType))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("不支持的支付方式: " + paymentType));
}
}
客户端使用
@RestController
@RequestMapping("/payments")
public class PaymentController {
@Autowired
private PaymentProcessorFactory paymentProcessorFactory;
@PostMapping("/process")
public ResponseEntity<PaymentResult> processPayment(@RequestBody PaymentRequest request) {
try {
PaymentProcessor processor = paymentProcessorFactory.createProcessor(request.getPaymentType());
PaymentResult result = processor.process(request);
return ResponseEntity.ok(result);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
PaymentResult.builder()
.success(false)
.message("支付处理失败: " + e.getMessage())
.build()
);
}
}
}
// 请求和结果DTO
public class PaymentRequest {
private String paymentType;
private BigDecimal amount;
private String orderId;
private String userId;
// getters and setters
}
public class PaymentResult {
private boolean success;
private String transactionId;
private String message;
// builder pattern implementation
}
3. 抽象工厂模式(Abstract Factory)
电商平台的多租户系统,不同租户需要不同的 UI 主题、数据库配置和缓存策略。
抽象产品接口
// UI主题接口
public interface UITheme {
String getPrimaryColor();
String getSecondaryColor();
String getLogoUrl();
String getThemeName();
}
// 数据库配置接口
public interface DatabaseConfig {
String getUrl();
String getUsername();
String getPassword();
int getMaxConnections();
}
// 缓存策略接口
public interface CacheStrategy {
void put(String key, Object value);
Object get(String key);
void remove(String key);
void clear();
}
具体产品类
// 企业版UI主题
@Component
public class EnterpriseUITheme implements UITheme {
@Override
public String getPrimaryColor() {
return "#1a365d";
}
@Override
public String getSecondaryColor() {
return "#2d3748";
}
@Override
public String getLogoUrl() {
return "/assets/enterprise-logo.png";
}
@Override
public String getThemeName() {
return "enterprise";
}
}
// 个人版UI主题
@Component
public class PersonalUITheme implements UITheme {
@Override
public String getPrimaryColor() {
return "#e53e3e";
}
@Override
public String getSecondaryColor() {
return "#f56565";
}
@Override
public String getLogoUrl() {
return "/assets/personal-logo.png";
}
@Override
public String getThemeName() {
return "personal";
}
}
// MySQL数据库配置
@Component
public class MySQLConfig implements DatabaseConfig {
@Value("${mysql.url}")
private String url;
@Value("${mysql.username}")
private String username;
@Value("${mysql.password}")
private String password;
@Override
public String getUrl() {
return url;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
@Override
public int getMaxConnections() {
return 100;
}
}
// PostgreSQL数据库配置
@Component
public class PostgreSQLConfig implements DatabaseConfig {
@Value("${postgresql.url}")
private String url;
@Value("${postgresql.username}")
private String username;
@Value("${postgresql.password}")
private String password;
@Override
public String getUrl() {
return url;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
@Override
public int getMaxConnections() {
return 50;
}
}
// Redis缓存策略
@Component
public class RedisCacheStrategy implements CacheStrategy {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public void put(String key, Object value) {
redisTemplate.opsForValue().set(key, value, Duration.ofHours(1));
}
@Override
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
@Override
public void remove(String key) {
redisTemplate.delete(key);
}
@Override
public void clear() {
// 清除所有缓存
Set<String> keys = redisTemplate.keys("*");
if (keys != null && !keys.isEmpty()) {
redisTemplate.delete(keys);
}
}
}
// 内存缓存策略
@Component
public class MemoryCacheStrategy implements CacheStrategy {
private final Map<String, Object> cache = new ConcurrentHashMap<>();
@Override
public void put(String key, Object value) {
cache.put(key, value);
}
@Override
public Object get(String key) {
return cache.get(key);
}
@Override
public void remove(String key) {
cache.remove(key);
}
@Override
public void clear() {
cache.clear();
}
}
抽象工厂接口
public interface TenantFactory {
UITheme createUITheme();
DatabaseConfig createDatabaseConfig();
CacheStrategy createCacheStrategy();
}
具体工厂类
// 企业版工厂
@Service("enterpriseFactory")
public class EnterpriseTenantFactory implements TenantFactory {
@Autowired
private EnterpriseUITheme uiTheme;
@Autowired
private MySQLConfig databaseConfig;
@Autowired
private RedisCacheStrategy cacheStrategy;
@Override
public UITheme createUITheme() {
return uiTheme;
}
@Override
public DatabaseConfig createDatabaseConfig() {
return databaseConfig;
}
@Override
public CacheStrategy createCacheStrategy() {
return cacheStrategy;
}
}
// 个人版工厂
@Service("personalFactory")
public class PersonalTenantFactory implements TenantFactory {
@Autowired
private PersonalUITheme uiTheme;
@Autowired
private PostgreSQLConfig databaseConfig;
@Autowired
private MemoryCacheStrategy cacheStrategy;
@Override
public UITheme createUITheme() {
return uiTheme;
}
@Override
public DatabaseConfig createDatabaseConfig() {
return databaseConfig;
}
@Override
public CacheStrategy createCacheStrategy() {
return cacheStrategy;
}
}
客户端使用
@RestController
@RequestMapping("/tenant")
public class TenantController {
@Autowired
@Qualifier("enterpriseFactory")
private TenantFactory enterpriseFactory;
@Autowired
@Qualifier("personalFactory")
private TenantFactory personalFactory;
@GetMapping("/config/{tenantType}")
public ResponseEntity<TenantConfig> getTenantConfig(@PathVariable String tenantType) {
TenantFactory factory = getFactoryByType(tenantType);
TenantConfig config = TenantConfig.builder()
.uiTheme(factory.createUITheme())
.databaseConfig(factory.createDatabaseConfig())
.cacheStrategy(factory.createCacheStrategy())
.build();
return ResponseEntity.ok(config);
}
private TenantFactory getFactoryByType(String tenantType) {
switch (tenantType.toLowerCase()) {
case "enterprise":
return enterpriseFactory;
case "personal":
return personalFactory;
default:
throw new IllegalArgumentException("未知的租户类型: " + tenantType);
}
}
}
// 配置DTO
public class TenantConfig {
private UITheme uiTheme;
private DatabaseConfig databaseConfig;
private CacheStrategy cacheStrategy;
// builder pattern implementation
}
运行结果
简单工厂模式示例
POST /products/create
{
"type": "electronic",
"name": "iPhone 15",
"price": 5999.00,
"attributes": {
"brand": "Apple"
}
}
响应: 商品创建成功: 电子产品 - Apple iPhone 15
工厂方法模式示例
POST /payments/process
{
"paymentType": "alipay",
"amount": 100.00,
"orderId": "ORD001",
"userId": "USER001"
}
响应: {
"success": true,
"transactionId": "ALI1703123456789",
"message": "支付宝支付成功"
}
抽象工厂模式示例
GET /tenant/config/enterprise
响应: {
"uiTheme": {
"primaryColor": "#1a365d",
"secondaryColor": "#2d3748",
"logoUrl": "/assets/enterprise-logo.png",
"themeName": "enterprise"
},
"databaseConfig": {
"url": "jdbc:mysql://localhost:3306/enterprise_db",
"username": "enterprise_user",
"password": "******",
"maxConnections": 100
},
"cacheStrategy": "Redis"
}
优点
- 封装创建逻辑:将对象的创建过程封装在工厂中,客户端不需要知道具体实现
- 解耦:客户端与具体产品类解耦,只依赖抽象接口
- 易于扩展:添加新产品时,只需要扩展工厂,不需要修改现有代码
- 统一管理:所有对象的创建都通过工厂统一管理
- 支持多态:通过接口实现多态,提高代码的灵活性
缺点
- 增加复杂度:引入了额外的抽象层,增加了系统的复杂度
- 类数量增加:工厂方法模式会导致类数量激增
- 可能过度设计:简单场景下可能显得过于复杂
- 违反开闭原则:简单工厂模式在添加新产品时需要修改工厂类
应用场景
- 商品管理系统:根据商品类型创建不同的商品对象
- 支付系统:根据支付方式创建不同的支付处理器
- 多租户系统:根据租户类型创建不同的配置组合
- 日志系统:根据日志级别创建不同的日志记录器
- 数据库连接:根据数据库类型创建不同的连接对象
- UI 组件:根据主题创建不同的 UI 组件
与其他模式的关系
- 与单例模式结合:工厂类可以使用单例模式确保全局唯一
- 与策略模式结合:工厂模式创建策略对象,策略模式执行具体算法
- 与建造者模式区别:工厂模式关注对象的创建,建造者模式关注对象的构建过程
- 与原型模式区别:工厂模式创建新对象,原型模式克隆现有对象
最佳实践
选择合适的工厂类型:
- 简单工厂:产品种类较少且相对固定
- 工厂方法:需要为每种产品提供专门创建逻辑
- 抽象工厂:需要创建一系列相关产品
工厂类设计:
- 确保工厂类职责单一
- 考虑使用依赖注入管理工厂对象
- 合理命名工厂方法
产品接口设计:
- 确保产品接口足够抽象
- 考虑产品的共同特征
- 支持未来的扩展
错误处理:
- 对不支持的产品类型提供明确的错误信息
- 考虑使用异常处理机制
总结
工厂模式是一种非常重要的创建型设计模式,它通过封装对象的创建过程来提高代码的可维护性和扩展性。在实际开发中,工厂模式经常与 Spring 框架的依赖注入机制结合使用,形成更加灵活和强大的解决方案。
选择合适的工厂模式类型对于项目的成功至关重要,需要根据具体的业务场景和需求来做出决策。同时,要注意避免过度设计,在简单场景下使用简单工厂模式就足够了。
