1、什么是策略模式?
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户端。
2、策略模式的结构
策略模式包含三个核心角色:
策略接口(Strategy):定义所有支持的算法的公共接口
具体策略类(ConcreteStrategy):实现策略接口的具体算法
上下文类(Context):持有一个策略对象的引用,提供给客户端使用
策略模式结构
3、实际应用场景
假设我们正在开发一个电商系统,需要根据不同的支付方式(支付宝、微信、银行卡)处理支付操作。
传统if-else实现
public class PaymentService {
public void pay(String paymentType, BigDecimal amount) {
if ("ALIPAY".equals(paymentType)) {
System.out.println("使用支付宝支付: " + amount);
// 支付宝支付的具体逻辑
} else if ("WECHAT".equals(paymentType)) {
System.out.println("使用微信支付: " + amount);
// 微信支付的具体逻辑
} else if ("BANK_CARD".equals(paymentType)) {
System.out.println("使用银行卡支付: " + amount);
// 银行卡支付的具体逻辑
} else {
throw new IllegalArgumentException("不支持的支付方式");
}
}
}
这种实现方式存在明显问题:
违反开闭原则,新增支付方式需要修改原有代码
代码臃肿,难以维护
条件判断逻辑复杂
实际开发中,这种是很常见的,不过我们还有更好的实现方式。
4、使用策略模式重构
4.1 定义策略接口
public interface PaymentStrategy {
void pay(BigDecimal amount);
}
4.2 实现具体策略类
// 支付宝支付策略
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
System.out.println("使用支付宝支付: " + amount);
// 具体的支付宝支付逻辑
}
}
// 微信支付策略
public class WechatPayStrategy implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
System.out.println("使用微信支付: " + amount);
// 具体的微信支付逻辑
}
}
// 银行卡支付策略
public class BankCardStrategy implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
System.out.println("使用银行卡支付: " + amount);
// 具体的银行卡支付逻辑
}
}
4.3 创建上下文类
public class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment(BigDecimal amount) {
strategy.pay(amount);
}
}
4.4 客户端使用
public class Client {
public static void main(String[] args) {
// 使用支付宝支付
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(100.0);
// 切换到微信支付
context.setStrategy(new WechatPayStrategy());
context.executePayment(200.0);
// 切换到银行卡支付
context.setStrategy(new BankCardStrategy());
context.executePayment(300.0);
}
}
4.5 结合工厂模式优化
为了减轻客户端了解具体策略的负担,可以结合工厂模式:
public class PaymentStrategyFactory {
private static final Map<String, PaymentStrategy> strategies = new HashMap<>();
static {
strategies.put("ALIPAY", new AlipayStrategy());
strategies.put("WECHAT", new WechatPayStrategy());
strategies.put("BANK_CARD", new BankCardStrategy());
}
public static PaymentStrategy getStrategy(String type) {
PaymentStrategy strategy = strategies.get(type);
if (strategy == null) {
throw new IllegalArgumentException("不支持的支付方式: " + type);
}
return strategy;
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
PaymentStrategy strategy = PaymentStrategyFactory.getStrategy("ALIPAY");
PaymentContext context = new PaymentContext(strategy);
context.executePayment(100.0);
}
}
5、策略模式的优缺点
优点:
符合开闭原则:新增策略无需修改现有代码;
避免多重条件判断:消除了大量的if-else或switch-case语句;
提高代码复用性:算法可以复用在多个上下文中;
易于扩展和维护:每个策略类单独维护,职责单一。
缺点:
客户端必须了解所有策略:客户端需要知道有哪些策略以及它们的区别;
策略类数量增多:每个策略都需要一个单独的类,可能需要创建多个策略对象。
6、Java中的策略模式应用
Java标准库中有许多策略模式的应用,例如:
Comparator接口:用于定义对象的比较策略;
ThreadPoolExecutor中的RejectedExecutionHandler:处理任务拒绝策略;
Java.security.Provider:提供加密算法策略;
Spring中的Bean实例化、AOP代理创建、缓存管理、事务管理等都用到了策略模式。
7、总结
策略模式通过将算法封装成独立的策略类,使得算法可以独立于客户端变化,提高了系统的灵活性和可扩展性。在实际开发中,策略模式常用于解决多重条件判断、算法选择等场景,是Java开发者必备的设计模式之一。
合理运用策略模式,可以使代码更加清晰、易于维护,并符合面向对象设计的原则。