模式的介绍
模式的定义
策略模式(Strategy Pattern)是一种比较简单的模式,定义如下:
Define a family of algorithms, encapsulate each one, and make them interchangeable.
定义一组算法,将每一组算法都封装起来,并且使它们之间可以互换。
模式的使用场景
- 多个类只有在算法或行为上稍有不同
- 算法需要自由切换
- 需要屏蔽算法规则
UML类图
角色介绍
- Context:用来操作策略的上下文环境
- Strategy : 策略的抽象。
- ConcreteStrategyA、ConcreteStrategyB : 具体的策略实现。
模式的简单实现
简单实现的介绍:
本来想自己做一个策略模式的样例,但是,还是还是要承认别人的这个样例更好,还是用别人的样例吧。
通常如果一个问题有多个解决方案或者稍有区别的操作时,最简单的方式就是利用if-else or switch-case方式来解决,对于简单的解决方案这样做无疑是比较简单、方便、快捷的,但是如果解决方案中包括大量的处理逻辑需要封装,或者处理方式变动较大的时候则就显得混乱、复杂,而策略模式则很好的解决了这样的问题,它将各种方案分离开来,让操作者根据具体的需求来动态的选择不同的策略方案。
这里以简单的计算操作(+、-、*、/)作为示例:
使用简单的if else
public static double calc(String op, double paramA, double paramB) {
if ("+".equals(op)) {
System.out.println("执行加法...");
return paramA + paramB;
} else if ("-".equals(op)) {
System.out.println("执行减法...");
return paramA - paramB;
} else if ("*".equals(op)) {
System.out.println("执行乘法...");
return paramA * paramB;
} else if ("/".equals(op)) {
System.out.println("执行除法...");
if (paramB == 0) {
throw new IllegalArgumentException("除数不能为0!");
}
return paramA / paramB;
} else {
throw new IllegalArgumentException("未找到计算方法!");
}
}
使用策略模式
UML类图
详细代码:
public interface Strategy {
public double calc(double paramA, double paramB);
}
加法的策略类
public class AddStrategy implements Strategy{
@Override
public double calc(double paramA, double paramB) {
// TODO Auto-generated method stub
System.out.println("执行加法策略...:"+(paramA + paramB));
return paramA + paramB;
}
}
减法的策略类
public class SubStrategy implements Strategy{
@Override
public double calc(double paramA, double paramB) {
// TODO Auto-generated method stub
System.out.println("执行减法策略...:"+(paramA - paramB));
return paramA - paramB;
}
}
乘法的策略类
public class MultiStrategy implements Strategy{
@Override
public double calc(double paramA, double paramB) {
// TODO Auto-generated method stub
System.out.println("执行乘法策略...:"+( paramA * paramB));
return paramA * paramB;
}
}
除法的策略类
public class DivStrategy implements Strategy {
@Override
public double calc(double paramA, double paramB) {
// TODO Auto-generated method stub
if(paramB == 0){
throw new IllegalArgumentException("除数不能为0!");
}
System.out.println("执行除法策略...:"+(paramA / paramB));
return paramA / paramB;
}
}
Context类 Calc:
public class Calc {
private Strategy strategy = null;
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public double calc(double paramA, double paramB) {
// TODO Auto-generated method stub
if (this.strategy == null) {
throw new IllegalStateException("你还没有设置计算的策略");
}
return this.strategy.calc(paramA, paramB);
}
}
main方法:
public class MainFunction {
public static void main(String[] args) {
// TODO Auto-generated method stub
double paramA = 5;
double paramB = 21;
System.out.println("------------- 普通形式 ----------------");
System.out.println("加法结果是:" + calc("+", paramA, paramB));
System.out.println("减法结果是:" + calc("-", paramA, paramB));
System.out.println("乘法结果是:" + calc("*", paramA, paramB));
System.out.println("除法结果是:" + calc("/", paramA, paramB));
System.out.println("------------ 策略模式 ----------------");
Calc calc = new Calc();
calc.setStrategy(new AddStrategy());
calc.calc(paramA, paramB);
calc.setStrategy(new SubStrategy());
calc.calc(paramA, paramB);
calc.setStrategy(new MultiStrategy());
calc.calc(paramA, paramB);
calc.setStrategy(new DivStrategy());
calc.calc(paramA, paramB);
}
public static double calc(String op, double paramA, double paramB) {
if ("+".equals(op)) {
System.out.println("执行加法...");
return paramA + paramB;
} else if ("-".equals(op)) {
System.out.println("执行减法...");
return paramA - paramB;
} else if ("*".equals(op)) {
System.out.println("执行乘法...");
return paramA * paramB;
} else if ("/".equals(op)) {
System.out.println("执行除法...");
if (paramB == 0) {
throw new IllegalArgumentException("除数不能为0!");
}
return paramA / paramB;
} else {
throw new IllegalArgumentException("未找到计算方法!");
}
}
}
程序输出:
------------- 普通形式 ----------------
执行加法...
加法结果是:26.0
执行减法...
减法结果是:-16.0
执行乘法...
乘法结果是:105.0
执行除法...
除法结果是:0.23809523809523808
------------ 策略模式 ----------------
执行加法策略...:26.0
执行减法策略...:-16.0
执行乘法策略...:105.0
执行除法策略...:0.23809523809523808
模式的优缺点
优点
- 算法可以自由的切换
- 避免使用多重条件判断
- 扩展性好
缺点
- 策略类数量增多
- 所有的策略类都需要对外暴露
Android源码中的模式实现
个人觉得策略模式应该在android中有许多应用,但是一时想不到什么特别好的例子,后补吧。
参考资料
(1).设计模式之禅—第18章 策略模式
(2)Android设计模式源码解析之策略模式
https://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/strategy/gkerison