策略模式概述
策略模式(Strategy Pattern)定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。该模式中一个类的行为或其算法可以在运行时更改,属于行为型模式。
比如在超市进行收银时,有时候会有活动例如:全部打八折、满100减10块,满300打九折。。。。。。在收银的时候收银员选择相应的结算方式进行计算最终结算金额,如果用if else判断的话,每次增加新的活动就要修改,这样扩展起来是非常不方便的,其实这些不同的活动都是一种策略,添加活动的时候增加一个策略就行了。
比如我们开发的时候会需要对数组排序,你可能根据不同的情况选用冒泡排序、选择排序、快速排序等,其实不同的排序方式都是一种算法策略,这种就非常适合用策略模式。
例如我们下面这种常用的list的排序,其实就是策略模式的体现
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add(20);
list.add(15);
list.add(15);
list.add(22);
Collections.sort(list, new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
System.out.println(list);
策略模式优缺点
- 优点:1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
- 缺点:1、策略类会增多。 2、所有策略类都需要对外暴露。
策略模式角色分配
- Strategy:抽象策略类或接口,定义了算法的公共接口
- ConcreteStrategy:具体的策略类,实现或者继承自Strategy,封装具体的算法或行为
- Context:内部包含一个Strategy的引用及策略的执行方法
其UML类图如下:
代码实现
策略接口如下,里面有一个方法,需要传入两个数字用于计算
public interface Strategy {
int doOperation(int num1,int num2);
}
具体的算法策略,提供了两个:加法和乘法
public class AddStrategy implements Strategy {
public int doOperation(int num1, int num2) {
return num1+num2;
}
}
public class MultiplyStrategy implements Strategy{
public int doOperation(int num1, int num2) {
return num1*num2;
}
}
Context上下文如下:
public class Context {
private Strategy s;
public Context(Strategy s) {
this.s = s;
}
public int executeStrategy(int num1,int num2){
return s.doOperation(num1, num2);
}
}
测试类如下:分别进行了加法和乘法运算,输出分别为5和6。如果我们想添加新的算法策略,Context类并不需要修改,这样扩展起来很方便,也不会修改原有代码。
public class Test {
public static void main(String[] args) {
Context context=new Context(new AddStrategy());
System.out.println(context.executeStrategy(2, 3));
context=new Context(new MultiplyStrategy());
System.out.println(context.executeStrategy(2, 3));
}
}