开放封闭原则(Open-Closed Principle:OCP)
开闭原则指的是, 对于扩展是开放的,对于修改是封闭的。软件设计的目标:封装变化、降低耦合,而OCP正是这目标最直接的提现之一。OCP优点就是不会对已有的代码造成影响,减小测试的范围,以及代码的稳定性。
策略模式
策略模式的功能主要是定义一系列算法,为了让这些算法可以相互替换。因此为这一系列算法定义公共的接口,用来约束这一系列算法要实现的功能。若这一系列算法具有公共功能,可以把策略接口实现为抽象类,把这些公共部分的功能实现到父类里面。
优点
避免多重条件语句:策略模式的一系列策略算法是平等的,可以互换的,写在一起就是通过if-else结构来组织,如果此时具体的算法实现里面又有条件语句,就构成了多重条件语句,使用策略模式能避免这样的多重条件语句。
更好的扩展性:在策略模式中扩展新的策略实现非常容易,只要增加新的策略实现类,然后在选择使用策略的地方选择使用这个新的策略实现就好了。
缺点
增加了对象数目:由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很多。
只适合扁平的算法结构:策略模式的一系列算法地位是平等的,是可以相互替换的,事实上构成了一个扁平的算法结构,也就是在一个策略接口下,有多个平等的策略算法,就相当于兄弟算法。而且在运行时刻只有一个算法被使用,这就限制了算法使用的层级,使用的时候不能被嵌套使用。
祭上策略模式经典结构图:

案例
假设我们要出去旅游,而去旅游出行的方式有很多,有步行,有坐火车,有坐飞机等等。而如果不使用任何模式,我们的代码可能就是这样子的。

这样做有一个致命的缺点,一旦出行的方式要增加,我们就不得不增加新的else if语句,而这违反了面向对象的原则之一,对修改封闭。而这时候,策略模式则可以完美的解决这一切。
首先,需要定义一个策略接口。

然后根据不同的出行方式实行对应的接口,

此外还需要一个包装策略的类,并调用策略接口中的方法,作为上下文使用:

实际使用:

可以看到,应用了策略模式后,如果我们想增加新的出行方式,完全不必要修改现有的类,我们只需要实现策略接口即可,这就是面向对象中的对扩展开放准则。假设现在我们增加了一种自行车出行的方式。只需新增一个类即可。
策略模式在Android中的应用
插值器TimeInterpolator.

我们知道,在属性动画中,有一个东西叫做插值器,它的作用就是根据时间流逝的百分比来来计算出当前属性值改变的百分比.我们使用属性动画的时候,可以通过set方法对插值器进行设置.可以看到内部维持了一个时间插值器的引用,并设置了getter和setter方法,默认情况下是先加速后减速的插值器,set方法如果传入的是null,则是线性插值器。

官方提供的LinearInterpolator,AccelerateDecelerateInterpolator等等之类的插值器都是通过实现TimeInterpolator再经过相关的函数计算得到相应的效果.

如果我们自己要定义不一样的加速效果,也可以通过实现TimeInterpolator来进行扩展.
类型估值器TypeEvaluator

属性动画中另外一个应用策略模式的地方就是估值器,它的作用是根据当前属性改变的百分比来计算改变后的属性值。该属性和插值器是类似的,有几个默认的实现。其中TypeEvaluator是一个接口。系统已经设计好的如,IntEvaluator,FloatEvaluator,PointFEvaluator等等
网友评论