设计模式——策略模式

本文介绍策略模式。

概念

定义一系列的算法,将每一个算法封装起来,并让他们可以相互替换。

结构和工作原理

  • Context:环境类,在解决某个问题的时候可以采用多种策略,环境类中持有抽象策略类的引用
  • Strategy:抽象策略类,为所支持的算法声明了抽象方法
  • ConcreteStrategy:具体策略类,是抽象策略类的子类,实现了抽象策略类中定义的算法

策略模式,顾名思义提供了解决问题的不同策略,我们根据环境或者某种条件来决定使用哪一种策略来完成该项任务。通过抽象,将策略建模抽取为抽象策略类,不同的策略用不同的具体策略类实现,使得不同策略的横向扩展变得简单,策略的替换也可以根据条件动态的替换选择。同时客户端在调用时不需要知道策略内部的具体执行,使得策略职责单一。

通常所有策略往往由一个KV Map容器持有,key为条件,value,环境类通过条件直接从策略容器中获取具体的策略。

策略模式容易理解,且使用场景十分广泛,在很多开源项目中都能见到其或其变种的身影。

策略模式将算法的职责与实现分开,通过抽象的方式将实现委派给具体实现类。

优点:

  • 策略模式提供了对开闭原则的完美支持
  • 使用策略模式避免了多重判断转移的条件语句

缺点:

  • 客户端必须知道所有策略适用的条件

代码示例

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayState {

private Boolean state;

private String msg;

}
public interface PayStrategy {

PayState pay(String account, BigDecimal amount);
}
@Slf4j
@Data
public class AliPay implements PayStrategy {

@Override
public PayState pay(String account, BigDecimal amount) {
log.info("AliPay- pay- account:{}, amount:{}", account, amount);
return PayState.builder().state(true).msg("pay success").build();
}
}
@Slf4j
@Data
public class PayPalPay implements PayStrategy {

@Override
public PayState pay(String account, BigDecimal amount) {
log.info("PayPalPay- pay- account:{}, amount:{}", account, amount);
return PayState.builder().state(false).msg("network error").build();
}
}
@Slf4j
@Data
public class WechatPay implements PayStrategy {

@Override
public PayState pay(String account, BigDecimal amount) {
log.info("WechatPay- pay- account:{}, amount:{}", account, amount);
return PayState.builder().state(true).msg("pay success").build();
}
}
public enum PayStrategyEnum {

ALI_PAY(new AliPay()),
WECHAT_PAY(new WechatPay()),
PAYPAL_PAY(new PayPalPay()),
;

private PayStrategy payStrategy;

PayStrategyEnum(PayStrategy payStrategy) {
this.payStrategy = payStrategy;
}

public PayStrategy getPayStrategy() {
return payStrategy;
}
}
public class PayStrategyCollection {

private static ConcurrentHashMap<String, PayStrategy> payStrategyConcurrentHashMap;

static {
payStrategyConcurrentHashMap = new ConcurrentHashMap<>();
payStrategyConcurrentHashMap.put("ALI", new AliPay());
payStrategyConcurrentHashMap.put("WECHAT", new WechatPay());
payStrategyConcurrentHashMap.put("PAYPAL", new PayPalPay());
}

public static PayStrategy getStrategy(String strategyName) {
return payStrategyConcurrentHashMap.get(strategyName);
}
}
public class StrategyClient {

public static void main(String[] args) {
String account = "myAccount";
BigDecimal amount = BigDecimal.valueOf(10000L);
PayStrategyEnum.ALI_PAY.getPayStrategy().pay(account, amount);
PayStrategyEnum.WECHAT_PAY.getPayStrategy().pay(account, amount);
PayStrategyEnum.PAYPAL_PAY.getPayStrategy().pay(account, amount);
PayStrategyCollection.getStrategy("ALI").pay(account, amount);
PayStrategyCollection.getStrategy("WECHAT").pay(account, amount);
PayStrategyCollection.getStrategy("PAYPAL").pay(account, amount);
}
}

参考资料

https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/strategy.html

Author: nopainanymore
Link: http://nopainanymore.me/DesignPattern-Strategy/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
wechat