源代码:https://gitee.com/AgentXiao/BehavioralPatterns
要点:
1、条件语句和策略模式的差异
2、策略模式的本质及实现
一、场景
某个的报价策略可以简单作如下分类:
• 普通客户小批量报价
• 普通客户大批量报价
• 老客户小批量报价
• 老客户大批量报价
具体选用哪个报价策略,这需要根据实际情况来确定。
我们可以使用一下机制实现:
public double getPrice(String type, double price){
if(type.equals("普通客户小批量")){
System.out.println("不打折,原价");
return price;
}else if(type.equals("普通客户大批量")){
System.out.println("打九折");
return price*0.9;
}else if(type.equals("老客户小批量")){
System.out.println("打八五折");
return price*0.85;
}else if(type.equals("老客户大批量")){
System.out.println("打八折");
return price*0.8;
} return price;
}
通过if-else if-else实现起来比较容易,符合开发人员的一般思路!但是当报价策略类型比较多,同时每个类型的报价方式比较复杂时,会导致整个条件控制语句非常地长,难以维护。
我们可以使用策略模式解决这个问题。
二、策略模式
策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便的更换算法或者增加新的算法。并且由客户端决定调用哪个算法。
也就是说,策略模式将每一种报价规格封装为一个类,这个类只解决这一种报价算法,在需要使用时以引用的方式注入。这就很好的解决了条件语句难以维护的难题。同时需要增加新的策略时,只需要新增一个类。
1、算法族通过一个接口将所有的具体算法聚集在一起
/**
* @interfaceName Strategy
* @Description 策略算法族
* @Author xwd
* @Date 2018/10/28 15:23
*/
public interface Strategy {
/**
* @MethodName getPrice
* @Descrition 价钱的计算方法
* @Param [price]
* @return double
*/
double getPrice(double price);
}
2、具体的算法按照实际情况进行确定,统一实现算法族接口
/**
* @ClassName NewCustomerFewStrategy
* @Description 新客户小批量
* @Author xwd
* @Date 2018/10/28 15:25
*/
public class NewCustomerFewStrategy implements Strategy {
@Override
public double getPrice(double price) {
System.out.println("新客户小批量:不打折!");
return price;
}
}
/**
* @ClassName NewCustomerFewStrategy
* @Description 新客户大批量
* @Author xwd
* @Date 2018/10/28 15:25
*/
public class NewCustomerManyStrategy implements Strategy {
@Override
public double getPrice(double price) {
System.out.println("新客户大批量:95折!");
return price*0.95;
}
}
/**
* @ClassName NewCustomerFewStrategy
* @Description 老客户小批量
* @Author xwd
* @Date 2018/10/28 15:25
*/
public class OldCustomerFewStrategy implements Strategy {
@Override
public double getPrice(double price) {
System.out.println("老客户小批量:9折!");
return price*0.9;
}
}
/**
* @ClassName NewCustomerFewStrategy
* @Description 老客户大批量
* @Author xwd
* @Date 2018/10/28 15:25
*/
public class OldCustomerManyStrategy implements Strategy {
@Override
public double getPrice(double price) {
System.out.println("老客户大批量:85折!");
return price*0.85;
}
}
3、需要一个管理算法族的类,作为客户和算法族之间的中间人(就像超超市的售货员),它持有算法族的引用,因此客户只需要和该中间人打交道,实现了客户和算法之间的解耦
/**
* @ClassName Boss
* @Description 商店老板,管理报价策略
* @Author xwd
* @Date 2018/10/28 15:29
*/
public class Boss {
private Strategy strategy;//持有报价策略的引用
public Boss(Strategy strategy) {
this.strategy = strategy;
}
/**
* @MethodName getPrice
* @Descrition 获得价格
* @Param [price]
* @return void
*/
public void getPrice(double price){
System.out.println("报价:"+this.strategy.getPrice(price));
}
}
4、客户,找到持有算法引用的中间人
/**
* @ClassName Client
* @Description 客户
* @Author xwd
* @Date 2018/10/28 15:32
*/
public class Client {
public static void main(String[] args) {
Boss boss = new Boss(new OldCustomerFewStrategy());
boss.getPrice(500);
}
}
5、测试结果
测试结果
三、总结
1、本质
分离算法,选择实现。
2、开发中常见的场景:
1)JAVASE中GUI编程中,布局管理
布局管理中有多种布局方式,例如流布局、边界布局等,在使用时直接指定相应的布局方式即可。
2)Spring框架中,Resource接口,资源访问策略
3)javax.servlet.http.HttpServlet#service()