策略模式

来源:互联网 发布:破壁料理机 知乎 编辑:程序博客网 时间:2024/06/03 20:28

记得刚毕业工作时,粗略翻看过关于设计模式的书,
之后在阅读android源码时,又断断续续地接触了些设计模式。

一直想找个机会认真总结一下这方面的内容,
拖延了好久,重于决定动手了。

在这篇博客中,我们的主角是策略模式。


我们先来看看一个具体的应用场景。

假设我们现在负责设计一个游戏中的各种角色,
例如骑士、战士、盗贼等。

显然,骑士、战士、盗贼作为角色,肯定有共同的部分,
因此我们首先会想到下面的设计方式:

Knight、Soldier和Thief均继承父类People,然后覆盖其中的fight和move函数,
以实现各自的打斗和移动方式。

在简单场景下,这么设计是可以满足需求的,
但在复杂场景下,这么设计缺乏灵活性。

例如,引入了武器系统后,Knight、Soldier和Thief的打斗方式可能与具体的武器有关;
引入坐骑系统后,三个子类的移动方式就可能与具体的坐骑有关。

同时,一个对象的武器和坐骑是可以改变的,
因此要求它的打斗方式与移动方式能够在运行时动态调整。

上图中提到的设计方式,将这些可能不断改变的部分与实际的对象绑定在一起,
显然是不满足设计要求的。

为了解决类似的问题,就需要使用策略模式了。


我们将设计方式变更为下图:

如上图所示,我们在父类中增加成员变量fightBehaviour和moveBehaviour。
这两个成员为接口类型,可以保存实际运行的对象。

同时,父类提供了setFightBehaviour和setMoveBehaviour函数,
用于调整fightBehaviour和moveBehaviour实际持有的对象,
以提供运行时动态调整的能力。

fight和move函数,将分别调用fightBehaviour和moveBehaviour的fight和move接口,
具体的功能由对应的子类来实现。

此时,People继承体系中变化的部分就被抽离出来了。

其中,所有实现FightBehaviour接口的类,构成了战斗算法族;
所有实现MoveBehaviour接口的类,构成了移动算法族。

Knight、Soldier和Thief可以动态地从战斗算法族中选择战斗方式,
从移动算法族中选择移动方式。

有了这个例子后,我们就可以来看看策略模式的定义了:
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。


现在,我们看一下Android中策略模式的例子。
我们以属性动画的用法为例:

............//xml定义的属性动画Animator anim = AnimatorInflater.loadAnimator(this, R.animator.set_simple);//设置具体的插值器anim.setInterpolator(new DecelerateInterpolator(2f));

从上面的代码可以看出,在创建动画对象后,我们可以动态的选择需要的插值器对象。

Android中对应的设计结构类似于下图:

容易看出,不同的插值器实现TimeInterpolator接口,
共同构成插值器算法族。
Animator及其子类可以动态使用算法族中的任意对象。

这就是很明显的策略模式。

1 0
原创粉丝点击