介绍:
软件开发过程中常遇到这种情况:实现某一个功能可以有多重算法或者策略,我们会根据情况不同选择不同的算法或者策略来完成该功能。
遇到这种情况,以前我的一般处理方法是将多种方法写在一个类中,调用的时候根据情况选择调用的方法。当然 ,也有人把这些算法写在一个函数里面,然后使用if...else...作为判断选择具体的算法,我们将这两种实现方法称之为硬编码。
但是,如果有很多很多的算法加入到选择中的时候,这个类就会显得臃肿,修改还比较麻烦,比较容易出错。如果我们要增加一个新的算法的时候,我们还需要更改算法的封装类。这个就很明显的违反了面向对象的开闭原则和单一职责原则,实不可取的。
所以我们需要把这些算法或者策略抽象出来,并提供一个统一的接口,不同的算法或策略有不同的实现类,这样在程序客户端就可以通过注入不同的实现对象来实现算法或策略的动态替换,这种模式的可扩展性强,可维护性更高。这个思想就是策略模式。
定义:
策略模式定义了一系列的算法,并且把每一个算法封装起来,而且使他们还可以互相替换。策略模式让算法独立于使用它的客户而独立变化。
使用场景:
- 针对同一类型问题的多钟处理方式,仅仅是具体行为有差别时。
- 需要安全的封装多种同一类型的操作时。
- 出现同一抽象类有多个子类,又不需要if...else...或者swich...case...来选择子类是。
角色:
- Context:用来操作策略的上下文环境
- Stragety:抽象的策略
- ConcreteStragety:具体的实现策略
简单实现:
package com.mabibin.eg.straregy;
/**
* 策略的抽象
* @author binbin.ma
*
*/
public interface CalculateStraregy {
String caculatePrice(int km) ;
}
package com.mabibin.eg.straregy;
/**
* 策略实现A
* @author binbin.ma
*
*/
public class BusStaregy implements CalculateStraregy {
@Override
public String caculatePrice(int km) {
return "乘坐公交车价格 * " + km ;
}
}
package com.mabibin.eg.straregy;
/**
* 策略实现B
* @author binbin.ma
*
*/
public class SubwayStaregy implements CalculateStraregy {
@Override
public String caculatePrice(int km) {
return "乘坐地铁价格 * "+km;
}
}
package com.mabibin.eg.straregy;
/**
* 上下文类
* @author binbin.ma
*
*/
public class TranficCalculator {
CalculateStraregy mStraregy ;
public void setStraregy(CalculateStraregy mStraregy){
this.mStraregy = mStraregy;
}
public String caculatePrice(int km) {
return mStraregy.caculatePrice(km);
}
}
package com.mabibin.eg.straregy;
public class Client {
public static void main(String[] args) {
TranficCalculator calculator = new TranficCalculator();
calculator.setStraregy(new SubwayStaregy());
System.out.println(calculator.caculatePrice(16));
}
}
用这种方法,解决了很多问题,如果使用if...else...来进行判断的话,虽然实现的较为简单,类型层次单一,但是代码臃肿,逻辑复杂,扩展性差,维护下差等缺点却是避之不开的。这种方法,建立了抽象,将不同的策略构建成一个具体的策略实现,实现不同的策略实现算法替换,在简化逻辑代码的同时,也增强了系统的可读性,稳定性,可拓展性。