定义
策略模式属于对象的行为模式。针对一组算法(行为,策略),将每一个算法封装到具有共同接口的独立的类中,从而使得他们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生改变。
解决问题
算法(行为)和客户端耦合在一起,客户端要利用条件选择语句来决定使用哪一个算法。使得客户端的代码变得复杂和难以维护,也不利于代码重用。
结构和角色
环境(Context)角色 : 持有一个Strategy类的引用。
抽象策略(Strategy)角色 : 所有具体策略的父类,可以是抽象类,接口,此角色用于定义具体策略类的行为。
具体策略(ConcreteStrategy)角色 : 封装具体的算法或行为。
public class Context { private Strategy strategy; // 省略 set get 方法 public void contextOperation() { strategy.operation(); } }
public interface Strategy{ public void operation(); } public class ConcreteStrategy implements Strategy{ public void operation() { // ... } } public class ConcreteStrategy2 implements Strategy{ public void operation() { // ... } }
项目中使用例子
项目的界面显示数据表有普通表格,自动排序,可拖拽,等几种表格。
Table和View是分离的,在View中可以根据需求设置Table。如果增加Table类型,不会影响到View。Table也是可重用的。
(二)
打印报表时,可以选择多种文件显示,这里也用到了策略模式。(具体省略)
使用场景
一个系统需要动态地在几种算法中选择一种。
一个系统的算法使用的数据不可以让客户端知道,即算法的具体实现对客户端是隐藏的。
如果一个对象有很多行为,且需要使用多重条件选择语句来实现。
优缺点
封装算法,使算法和客户端分离,降低耦合,使得算法本身具有可重用性。
策略模式提供了管理相关的算法族的方法,策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免重复代码。
策略模式提供了替换继承关系的办法。
避免使用多重条件转移语句。
缺点
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
策略模式造成很多的策略类。
Strategy模式背后的三个面向对象设计原则:
封装变化,算法是可以变化的,所以将它与客户端分离使得算法的变化不影响客户端,降低耦合。封装后的算法可重用。
面向接口编程,要使具体策略类能够相互替换,那么客户端内必须要有他们共同的接口。
组合优于继承,环境类使用的是组合而非继承。