核心思想
策略模式的核心目的在于:解决 算法 / 行为选择 问题:封装不同的业务逻辑(算法),让逻辑可替换、可扩展
核心角色
通用的抽象策略
是一个接口,定义了不同业务逻辑算法相同的抽象,相同的入参,相同的返回值类型
策略实现类
实现通用的抽象策略接口
策略上下文
选择和使用不同的策略
业务注入
在业务中使用时,通过上下文来选择使用不同策略
代码实践
我们以经典的支付问题为例,原先没有使用设计模式的代码是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| @Service public class PaymentService { public static final String ALIPAY = "alipay"; public static final String WECHAT_PAY = "wechat";
public void pay(String paymentType, double amount, String accountInfo) { System.out.println("开始支付..."); if (ALIPAY.equals(paymentType)) { System.out.println("使用支付宝账户 " + accountInfo + " 支付了 " + amount + " 元"); System.out.println("支付宝支付成功!"); } else if (WECHAT_PAY.equals(paymentType)) { System.out.println("使用微信账号 " + accountInfo + " 支付了 " + amount + " 元"); System.out.println("微信支付成功!"); } else { throw new IllegalArgumentException("不支持的支付方式:" + paymentType); } } }
|
如果支付方式越来越多,Service中的pay方法就会非常冗长,不好维护并且耦合度太高
我们可以采用策略模式进行重构
策略模式本质上是使用了面向对象中接口的特性
对于上述应用场景,我们可以将【支付】这一个主题抽象一种策略,一个策略具体对应到代码就是一个接口
通用的抽象策略
1 2 3 4 5 6 7 8 9
| public interface PaymentStrategy {
void pay(double amount);
String getPaymentName(); }
|
策略实现类
1 2 3 4 5 6 7 8 9 10 11
| public class WechatStrategy implements PaymentStrategy{ @Override public void pay(double amount) { System.out.println("Successfully pay " + amount + " with " + getPaymentName()); }
@Override public String getPaymentName() { return "Wechat Pay"; } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class AlipayStrategy implements PaymentStrategy{ @Override public void pay(double amount) { System.out.println("Alipay login ..."); System.out.println("Successfully pay " + amount + " with " + getPaymentName()); }
@Override public String getPaymentName() { return "Alipay"; } }
|
策略上下文
1 2 3 4 5 6 7 8 9 10 11 12
| public class PaymentContext { public PaymentStrategy getStrategyByPayType(String payType) { switch (payType) { case "WECHAT": return new WechatStrategy(); case "ALIPAY": return new AlipayStrategy(); default: throw new IllegalArgumentException("不支持的支付类型:" + payType); } } }
|
业务注入
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class PaymentService {
private final PaymentContext paymentContext;
public PaymentService(PaymentContext paymentContext) { this.paymentContext = paymentContext; }
public void pay(String payType, double amount) { PaymentStrategy strategy = this.paymentContext.getStrategyByPayType(payType); strategy.pay(amount); } }
|
模拟调用Service的客户端
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class StrategyTest { public static void main(String[] args) {
PaymentContext context = new PaymentContext(); PaymentService service = new PaymentService(context);
service.doPay("WECHAT", 2.3);
System.out.println("-----");
service.doPay("ALIPAY", 2.3); } }
|
总结
和工厂方法模式的区别
策略模式和工厂方法设计模式的核心区别在于应用的场景(也就是设计的目的)完全不同
- 策略模式关注的是:将算法/业务逻辑进行封装抽象
- 工厂方法模式关注的是:将业务对象的创建过程进行封装,使用方只关注业务使用,工厂只关注业务对象的创建
当核心需求是逻辑选择
而非对象创建
,且 对象创建相关的业务逻辑足够简单时,无需额外引入工厂方法模式,直接用策略模式即可满足需求