一、什么是策略模式?
策略模式(Strategy Pattern)是一种行为型设计模式,它将一组算法或业务逻辑封装为独立的策略类,使这些策略可以互换使用,并通过上下文类动态选择合适的策略。
核心思想
• 将不同的行为或算法独立封装为策略类,客户端无需关注内部实现逻辑。
• 遵循开闭原则(OCP),新增策略时无需修改已有代码,避免复杂的if-else判断逻辑。
策略模式的关键结构
1.策略接口(Strategy)
定义一组算法的通用接口。
2.具体策略(Concrete Strategy)
每个具体策略实现不同的算法。
3上下文类(Context)
上下文类持有策略接口的引用,用于调用具体策略。
二、策略模式的实际案例
场景:订单支付系统(支持支付宝、微信和银联支付)。
直接实现(未使用策略模式):
java
public class PaymentService {
public void pay(String paymentType, double amount) {
// 支付宝支付
if ("ALIPAY".equals(paymentType)) {
System.out.println("Using Alipay to pay: " + amount);
// 微信支付
} else if ("WECHAT".equals(paymentType)) {
System.out.println("Using WeChat Pay to pay: " + amount);
// 银联支付
} else if ("UNIONPAY".equals(paymentType)) {
System.out.println("Using UnionPay to pay: " + amount);
} else {
System.out.println("Unsupported payment type!");
}
}
}
问题分析
1.违反开闭原则:每新增一种支付方式,都需要修改pay()方法,代码难以维护。
2.可读性和扩展性差:复杂条件判断导致代码臃肿,增加阅读和测试成本。
3.高耦合性:支付逻辑直接耦合在调用代码中,难以重用和扩展。
使用策略模式实现
1.定义支付策略接口
策略模式的第一步是定义一个接口,抽象出所有支付方式的共同行为。
java
/**
* 支付策略接口,所有支付方式必须实现该接口。
*/
public interface PaymentStrategy {
/**
* 执行支付操作
* @param amount 支付金额
*/
void pay(double amount);
}
2.实现具体的支付策略类
每个支付方式对应一个实现类,独立封装具体的支付逻辑。
java
/**
* 支付宝支付策略
*/
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用支付宝支付了 " + amount + " 元");
}
}
/**
* 微信支付策略
*/
public class WeChatPayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用微信支付了 " + amount + " 元");
}
}
/**
* 银联支付策略
*/
public class UnionPayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用银联支付了 " + amount + " 元");
}
}
3.定义支付上下文类
上下文类负责持有具体的策略对象,并在需要时调用对应的支付逻辑。
java
/**
* 支付上下文类,用于管理支付策略
*/
public class PaymentContext {
// 策略对象
private PaymentStrategy paymentStrategy;
/**
* 构造方法,初始化支付策略
*/
public PaymentContext(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
/**
* 执行支付操作
* @param amount 支付金额
*/
public void executePayment(double amount) {
paymentStrategy.pay(amount);
}
}
4.客户端代码:选择支付方式并支付
客户端通过选择不同的策略,实现不同的支付方式。
java
/**
* 客户端测试代码
*/
public class Client {
public static void main(String[] args) {
double amount = 200.0; // 支付金额
// 使用支付宝支付
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(amount);
// 使用微信支付
context = new PaymentContext(new WeChatPayStrategy());
context.executePayment(amount);
// 使用银联支付
context = new PaymentContext(new UnionPayStrategy());
context.executePayment(amount);
}
}
运行结果:
bash
使用支付宝支付了 200.0 元
使用微信支付了 200.0 元
使用银联支付了 200.0 元
代码结构说明
1.策略接口PaymentStrategy
定义支付方法pay(),所有支付类须实现它。
2.具体策略类
AlipayStrategy:实现支付宝支付逻辑。
WeChatPayStrategy:微信支付逻辑。
UnionPayStrategy:实现银联支付逻辑。
3.上下文类PaymentContext
维护一个策略对象,客户端可以动态选择不同的支付策略。
4.客户端
通过创建不同的支付策略对象,实现灵活的支付功能。
三、策略模式的价值
1.简化主逻辑,消除复杂条件判断
策略模式将复杂的if-else或switch-case语句分解为独立的策略类,使主逻辑更专注于调用流程(上下文),代码清晰且易维护。
2.便于扩展,符合开闭原则
新增功能(如支付方式)时,只需新增策略类,无需修改现有代码,既减少对稳定模块的干扰,也降低扩展成本。
3.提升复用性
策略类通过模块化设计,将具体逻辑与选择逻辑分离,可直接复用于其他系统。
四、适用场景
1.动态行为选择
系统需要在运行时根据不同条件选择不同的行为或算法,例如支付方式切换、促销规则变化、日志格式化样式调整等。
2.简化条件分支
当代码中存在大量if-else或switch-case时,且未来可能增加判断分支时,可通过策略模式优化为独立的策略类,提升可维护性。
3.高扩展性需求
系统需要频繁新增功能,但不希望频繁修改现有代码,策略模式符合开闭原则(OCP)。
4.测试驱动开发场景
需要对不同行为进行独立验证时,策略模式将这些行为解耦,便于单独测试。
五、总结
策略模式通过将行为或算法封装为独立类,结合上下文动态选择策略,提升了系统的灵活性、扩展性与可维护性。
核心价值
• 开发上,简化主逻辑,消除复杂条件判断,增强扩展性与复用性。
• 测试上,降低模块间耦合性,简化单元测试,降低回归测试成本。
1.策略类过多可能导致类数量膨胀,应合理设计。
2.在简单场景下,策略模式可能显得"过度设计",需权衡实际需求。