目录
Strategy(策略,Behavioral Pattern)
问题:鸭子游戏
- 我要创建一堆鸭子类,它们能叫,能游泳,但是有着不同的性状
- 首先我们想整一种红头鸭和绿头鸭
- 基本想法是这样,就继承呗,
- 想让鸭子飞也简单,直接在父类里面加一个方法
- 可如果我要有橡皮鸭子咋办泥
- 可能需要重写父类的方法
- 这样就违反了之前的里氏替换原则
- 把可能变化的代码独立出来,不要和不变化的代码混在一起
- 针对接口编程,而不是针对实现编程
Strategy Pattern
它是啥
- 针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。客户决定使用哪个算法。
- 简单来说,就是把要变的部分改成接口,然后不同的策略都实现这个接口,再用组合/聚合的方法把接口放在需要使用不同策略的地方
啥时用
- 许多相关的类只是行为不同时
- 一种算法需要不同的算法变体
- 使用策略模式避免暴露复杂的、针对算法的数据结构
- 有许多条件分支时,把不同分支内的东西放进不同的策略类,减少if语句的使用
怎么用
- 策略模式主要有三部分:策略、上下文、实体策略类
- 策略:这部分主要是定义一个抽象的接口,上下文通过调用这个接口的方法来调用不同的实体策略类
- 实体策略类:用不同的算法实现策略接口
- 上下文:有一个策略接口的对象的引用
- 交互方式:
- 策略与上下文的交互:上下文可以把策略算法需要的数据传给算法,也可以把自己作为引用传入,类似观察者模式中的推拉两种模型
- 客户端与策略的交互:客户端通常有多种策略算法可以选择,通过上下文把客户端的需求转发给策略接口,客户端一般创建一个实体策略对象传给上下文
优缺点
- 好处:
- 可以提供多种策略
- 可以作为继承的替代,把多种策略封装起来
- 可以减少条件语句的使用,作为条件语句的替代
- 可以方便客户端选择多种不同的实现
- 缺点
- 客户要知道不同的策略,增大了难度
- 上下文传输给不同策略的数据可能不能被完全使用,造成浪费
- 对象的数量变多了
例子:LayoutManager in AWT
- 在给一个容器设置布局的时候,我们传的是一个新的布局的对象
- 不同的布局就是不同的策略,它们都实现一个布局管理器的接口,而容器类中有一个接口的引用,只要把一个实体的布局对象传给容器对象,就可以使用不同的布局了
- 下图为容器类中设置布局的方法
- 下图是布局管理器接口
- 下图是一个实体布局类的定义
实例:排序系统