应用场景
实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。
如编写排序算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…或者case等条件判断语句来进行选择。这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。如果我们将这些策略包含在客户端,这种做法更不可取,将导致客户端程序庞大而且难以维护,如果存在大量可供选择的算法时问题将变得更加严重。
策略模式体现了两个非常基本的面向对象设计的原则:
1.封装变化的概念。
2.编程中使用接口,而不是对接口的实现
在JDK中的体现
定义一组算法,并把其封装到一个对象中。然后在运行时,可以灵活的使用其中的一个算法。
java.util.Comparator#compare()
javax.servlet.http.HttpServlet
javax.servlet.Filter#doFilter()
参与角色
环境类(Context):用一个ConcreteStrategy对象来配置。
维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。
抽象策略类(Strategy):定义所有支持的算法的公共接口。
Context使用这个接口来调用某ConcreteStrategy定义的算法。
具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法。
编写策略模式的一般步骤:
1.对策略对象定义一个公共接口
2.编写具体策略类,该类实现了上面的接口
3.在使用策略对象的类(即:环境角色)中保存一个对策略对象的引用
4.在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值
5.客户端进行调用
使用策略模式实例
抽象策略类(Strategy):
public interface SortStrategy { public int[] sort(int[] arr); }
具体策略类(ConcreteStrategy):
public class InsertionSort implements SortStrategy{ @Override
public int[] sort(int[] arr) {
return arr;
} }
public class SelectionSort implements SortStrategy{ @Override
public int[] sort(int[] arr) {
return arr;
} }
环境类(Context):
public class Context { private SortStrategy strategy; public Context(SortStrategy strategy){
this.strategy = strategy;
} public void muiltySort(int[] arr){
strategy.sort(arr);
} }
策略模式的缺点
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类;
2.造成很多的策略类;