「扫码关注我,面试、各种技术(mysql、zookeeper、微服务、redis、jvm)持续更新中~」
策略模式标准定义:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
策略(Strategy)模式属于对象的行为模式,通过分析Strategy模式可以发现:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。
在软件设计中,经常会遇到因为一开始考虑不够长远而导致后面遇到很大的麻烦。开发者只是想尽快地解决问题而没考虑到后期的维护或者根本没法预料到将来会有什么样的变化干脆置之不理。针对这个问题,Strategy模式提供了一个解决问题的方案:面向接口编程而不是实现,发现其中会改变的部分作为扩展点,然后把它封装起来。
下是对实际开发中计算支付费率if的改造,原始代码:
/**
* if方式计算三方支付手续费
*/
public class Example1 {
/**
* @param payTypeName 支付方式名称
* @param price 付款金额
* @return
*/
public static Double calculateFee(String payTypeName, Double price){
if(Objects.equals("支付宝",payTypeName)){
return price * 0.0006;
}else if(Objects.equals("微信",payTypeName)){
return price * 0.0003;
}else if(Objects.equals("招商app",payTypeName)){
return price * 0.0003;
}else if(Objects.equals("智能pos",payTypeName)){
return price * 0.0006;
}
return null;
}
}
下面通过策略模式进行优化改造:抽象Strategy
/**
* 策略接口类
*/
public interface Strategy {
Double calculateFee(Double price);
}
具体环境(角色)
/**
* 财务实体类
*/
public class Finance {
//引入策略
private Strategy strategy;
public Finance(Strategy strategy){
this.strategy=strategy;
}
public double calculateFee(double price){
return this.strategy.calculateFee(price);
}
}
具体策略
/**
* 支付宝计算手续费策略
*/
public class AliPayStrategy implements Strategy{
@Override
public Double calculateFee(Double price) {
return price * 0.006;
}
}
/**
* 微信计算手续费策略
*/
public class WechatPayStrategy implements Strategy{
@Override
public Double calculateFee(Double price) {
return price * 0.003;
}
}
/**
* 交行pos计算手续费策略
*/
public class PosPayStrategy implements Strategy{
@Override
public Double calculateFee(Double price) {
return price * 0.006;
}
}
/**
* 招行一网通计算手续费策略
*/
public class CMBPayStrategy implements Strategy{
@Override
public Double calculateFee(Double price) {
return price * 0.003;
}
}
实际应用过程
/**
* 测试策略模式
*/
public class TestStrategy {
public static void main(String[] args) {
double price = 1000;
//计算支付宝费率
AliPayStrategy aliPayStrategy = new AliPayStrategy();
System.out.println(new Finance(aliPayStrategy).calculateFee(price));
//计算微信支付费率
WechatPayStrategy wechatPayStrategy = new WechatPayStrategy();
System.out.println(new Finance(wechatPayStrategy).calculateFee(price));
}
}
总结
策略模式的优点
- 易于扩展,增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合开放封闭原则
- 避免使用多重条件选择语句,充分体现面向对象设计思想 策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以自由切换
- 每个策略类使用一个策略类,符合单一职责原则 客户端与策略算法解耦,两者都依赖于抽象策略接口,符合依赖反转原则
- 客户端不需要知道都有哪些策略类,符合最小知识原则
策略模式的缺点
- 策略模式,当策略算法太多时,会造成很多的策略类
- 客户端不知道有哪些策略类,不能决定使用哪个策略类,这点可以考虑使用IOC容器和依赖注入的方式来解决