策略模式
- 最近项目中 if else用的太多 想着重构换一种更为优雅的方式,于是发现了设计模式中的策略模式就是避免if else 很好的一种办法,借此好好学习,仅以本博客记录学习的一些知识点,以便日后回顾。如有不对,欢迎指出。
- 应用场景
- 比如对于一个系统拥有不同类型的客户,针对不同类型的客户提供不同的服务。怎么来处理这一业务逻辑,废话不多说直接先亮出代码,本文代码参考其他一些其他博客。
- 策略模式相关实现
- 策略的抽象
public interface Strategy {
public double calRecharge(Double charge,RechargeTypeEnum rechargeTypeEnum);
}
- 策略的工厂类
public class StrategyFactory {
private static StrategyFactory factory = new StrategyFactory();
private StrategyFactory(){
}
private static HashMap<Integer, Strategy> strategyMap = new HashMap<>();
static {
strategyMap.put(RechargeTypeEnum.E_BANK.value(),new EBankStrategy());
strategyMap.put(RechargeTypeEnum.BUSI_ACCOUNTS.value(),new BusiAcctStrategy());
}
// 单例模式
public Strategy create(Integer type){
return strategyMap.get(type);
}
public static StrategyFactory getInstance(){
return factory;
}
}
- 具体某一策略(枚举)
public enum RechargeTypeEnum {
E_BANK(1, "网银"),
BUSI_ACCOUNTS(2, "商户账号"),
MOBILE(3,"手机卡充值"),
CARD_RECHARGE(4,"充值卡");
private int value;
private String description;
private RechargeTypeEnum(int value, String description){
this.value = value;
this.description = description;
}
public int value() {
return value;
}
public String description() {
return description;
}
public static RechargeTypeEnum valueOf(int value) {
for(RechargeTypeEnum type : RechargeTypeEnum.values()) {
if(type.value() == value) {
return type;
}
}
return null;
}
}
- 不同策略的算法
public class EBankStrategy implements Strategy {
@Override
public double calRecharge(Double charge, RechargeTypeEnum rechargeTypeEnum) {
return 0.85*charge;
}
}
public class BusiAcctStrategy implements Strategy {
@Override
public double calRecharge(Double charge, RechargeTypeEnum rechargeTypeEnum) {
return 0.75*charge;
}
}
- 策略的环境类封装
public class Context {
private Strategy strategy;
public double calStrategy(Double charge,Integer type){
// 工厂方法
strategy = StrategyFactory.getInstance().create(type);
return strategy.calRecharge(charge,RechargeTypeEnum.valueOf(type));
}
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
}
- 测试代码
public class Client {
public static void main(String[] args) {
Context context = new Context();
double money = context.calStrategy(1.0,1);
System.out.println(money);
}
}
- 看完上面的代码,应该知道策略模式大致是一个怎么样的存在与使用
- 它其实就是将算法的责任与具体实现进行进一步的隔离与封装,不同的策略委托给不同的对象来处理。
- 它对于开闭原则的支持堪称完美,可以不改变原有系统的基础上选择算法,同时维护新的算法。
- 避免了if else的泛滥
- 不足之处
- 用户必须对所有的算法了解,以便选择需要的策略
- 每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况
- 适用场景
-
一个系统需要动态地在几种算法中选择一种,那么可以将这些算法封装到一个个的具体算法类中,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,根据“里氏代换原则”和面向对象的多态性,客户端可以选择使用任何一个具体算法类,并只需要维持一个数据类型是抽象算法类的对象。
-
一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句
-
不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法与相关的数据结构,可以提高算法的保密性与安全性
-
- 延伸思考
- 如何将现有系统中的代码抽取为策略模式
- 规则引擎 drools