最近公司项目有这样一种需求:需要根据几种不同的算法来对同一组数据进行不同的处理。例如:计算某一天的平均值,最大值,最小值或者记录次数。
很明显,这里其实是涉及到同一组数据的不同算法策略。而且这每一个策略都是平级关系,互相之间可以替换。为了更好的解耦和尽可能的使程序符合开闭原则,一个很好的方式就是使用设计模式中的策略模式。
策略模式相对来说是一个比较好理解的设计模式。先来看一下策略模式的UML类图:
策略模式主要有这样几个成员:
IStrategy:抽象策略接口。
StrategyImpl01等:抽象策略的具体实现类。
Context:策略操作的上下文。用来解耦调用者和具体策略。
因此我们可以知道策略模式的具体作用。就是将具体的算法策略进行单独的封装,利用面向接口编程和上下文类,将策略与调用者进行完全解耦。这样后面如果策略更改,只需要修改相应的策略实现类。如果有策略增加,也只需要增加相应的策略实现类即可。
接下来看一个简单的例子:就拿开头说的需求,我们来改一下看看。
目前有4种算法:平均值算法,最大值算法,最小值算法,计数算法。由Client来决定调用哪一个算法。
1、首先来看第1种实现,这种实现我们不采用策略模式:
算法类:
class Cal{
private static final String AVG = "AVG";
private static final String MAX = "MAX";
private static final String MIN = "MIN";
private static final String COUNT = "COUNT";
public void cal(String calString){
if(AVG.equals(calString)){
avg();
}else if(MAX.equals(calString)){
max();
}else if(MIN.equals(calString)){
min();
}else if(COUNT.equals(calString)){
count();
}
}
private void avg(){
System.out.println("平均值算法");
}
private void max(){
System.out.println("最大值算法");
}
private void min(){
System.out.println("最小值算法");
}
private void count(){
System.out.println("计数算法");
}
}
客户类:
class Client01 {
public static void main(String[] args) {
Cal cal = new Cal();
cal.cal("MAX");
}
}
这种实现有什么问题呢?
可以看到,目前所有的算法方法全部在Cal这个类中。如果旧的算法需要更改,或者又来了新的算法,我们都需要去更改Cal这个类。而且随着新算法的增加,这个类的代码会不断扩大。
2、接下来,我们引入策略模式来实现。
抽象策略接口:
interface IStrategy {
void algorithm();
}
各个策略的具体实现类:
class AvgStrategy implements IStrategy{
public void algorithm(){
System.out.println("平均值算法");
}
}
class MaxStrategy implements IStrategy{
public void algorithm(){
System.out.println("最大值算法");
}
}
class MinStrategy implements IStrategy{
public void algorithm(){
System.out.println("最小值算法");
}
}
class CountStrategy implements IStrategy{
public void algorithm(){
System.out.println("计数算法");
}
}
上下文操作类:
class StrategyContext{
private IStrategy mIStrategy;
public void setIStrategy(IStrategy iStrategy){
mIStrategy = iStrategy;
}
public void algorithm(){
if(mIStrategy!=null){
mIStrategy.algorithm();
}
}
}
客户类:
class Client02 {
public static void main(String[] args) {
StrategyContext strategyContext = new StrategyContext();
strategyContext.setIStrategy(new CountStrategy());
strategyContext.algorithm();
}
}
可以看到虽然类增多了,但是各个算法被解耦成了单独的类。结构变得十分清晰对不对。如果这时需要修改已有算法,那么我们只需要到相应的实现类中去做调整即可。完全不可能影响到其他算法。而且如果有新的算法,我们只要增加一个IStrategy的实现类即可,十分灵活。这就是策略模式的好处。
参考:《设计模式之禅》,《Android源码设计模式解析与实战》