一 . 什么是策略模式
策略模式是对算法的包装,把使用算法的责任和算法本身分隔开,委派给不同的对象管理。策略模式通常把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。
简单来说就是就定义一个策略接口,子类策略去实现该接口去定义不同的策略。然后定义一个环境(Context)类,以策略接口作为成员变量,根据环境来使用具体的策略。
二. 使用场景
业务中有要根据不同条件来使用不同算法的情况下,并且这些算法可以抽象的,就可以去使用。例如说,根据用户的分类,可以分为普通用户、白金用户、钻石用户等,不同种类的用户结算时需要不同的结算算法。如果不使用的话,那么可能造成每增加用户种类就需要去,就要在业务代码上去增加一个判断,造成的后果就是代码越来越冗余,不利于维护,也不方便阅读。
三. 如何使用
1.定义策略接口
1 public interfaceStrategy {2
3 publicDouble count(Double pay);4 }
2.不同策略实现该策略接口
//普通会员 全款
public class StrategyNormal implementsStrategy {
@OverridepublicDouble count(Double pay) {returnpay ;
}
}//白金会员98折
public class StrstegyPlatinum implementsStrategy {
@OverridepublicDouble count(Double pay) {return pay * 0.98;
}
}//钻石会员9折
public class StrstegyDiamond implementsStrategy {
@OverridepublicDouble count(Double pay) {return pay * 0.9;
}
}
3.定义策略环境
public classContext {privateStrategy strategy;publicContext(Strategy strategy) {this.strategy =strategy;
}publicDouble count(Double pay){returnstrategy.count(pay);
}
4.定义策略工厂
为什么有策略工厂?因为在策略环境Context 中需要具体的策略实现类去进行算法计算的,所以需要根据客户端给出的条件去具体的拿到策略类。
首先我们定义一个枚举类,定义不同的用户级别
public enumCustomerType {
NORMAL(0,"普通用户"),
PLATINUM(1,"白金用户"),
DUAMOND(2,"钻石用户");private intindex;privateString message;
CustomerType(intindex, String message) {this.index =index;this.message =message;
}
@OverridepublicString toString() {return "CustomerType{" +
"index=" + this.index +
", message='" + this.message + '\'' +
'}';
}
定义具体的策略工厂。
public class StrategyFactory {
private static Map strstegyMap = new HashMap();
public static void register(CustomerType type, Strategy strategy){
strstegyMap.put(type,strategy);
}
private StrategyFactory() {
}
public static Strategy getInstance(CustomerType type){
return strstegyMap.get(type);
}
}
5.调用
public static voidmain(String[] args) {
Double pay= 100.00D;
Strategy strategyNormal=StrategyFactory.getInstance(CustomerType.NORMAL);
Context contextNormal= newContext(strategyNormal);
System.out.println(CustomerType.NORMAL.toString()+ "应付:" +contextNormal.count(pay));
Strategy strategyPlatinum=StrategyFactory.getInstance(CustomerType.PLATINUM);
Context contextPlatinum= newContext(strategyPlatinum);
System.out.println(CustomerType.PLATINUM.toString()+ "应付:" +contextPlatinum.count(pay));
Strategy strategyDuamond=StrategyFactory.getInstance(CustomerType.DUAMOND);
Context contextDuamond= newContext(strategyDuamond);
System.out.println(CustomerType.DUAMOND.toString()+ "应付:"+contextDuamond.count(pay));
}
结果:
CustomerType{index=0, message='普通用户'}应付:100.0CustomerType{index=1, message='白金用户'}应付:98.0CustomerType{index=2, message='钻石用户'}应付:90.0
这样的话,以后如果还要加别的会员类型,直接在枚举兑现各种增加类型,然后实现策略接口,在策略工厂中稍作修改就可以实现功能,不用去修改业务主体代码,减少了if else 的判断。
四、优化
每增加一个用户类型后,还是需要去修改策略工厂类,我在想有没有办法去根据客户端的类型,动态加载子类策略的方法。
后来看到有网友通过使用反射以及注解的方式实现了动态加载,根据这个思路继续做一个调整。
//客户端类型注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)public @interfaceCustomerTypeAnnotation {
CustomerType customerType()defaultCustomerType.NORMAL;
}
未完待续=======