这个系列停更了好久了,差不多可以重新拿起来更一篇了,这篇文章主要介绍策略模式。在这之前,先温习一下前面介绍的4种模式。
很重要!
很重要!
设计模式很重要!
接着看下策略模式的定义
策略模式定义了一些列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变换。
乍一看,也没看出个所以然来。举个栗子吧。
假设我们要出去旅游,而去旅游出行的方式有很多,有步行,有坐火车,有坐飞机等等。而如果不使用任何模式,我们的代码可能就是这样子的。
public class TravelStrategy { enum Strategy{ WALK,PLANE,SUBWAY } private Strategy strategy; public TravelStrategy(Strategy strategy){ this.strategy=strategy; } public void travel(){ if(strategy==Strategy.WALK){ print(walk); }else if(strategy==Strategy.PLANE){ print(plane); }else if(strategy==Strategy.SUBWAY){ print(subway); } } public void print(String str){ System.out.println(出行旅游的方式为:+str); } public static void main(String[] args) { TravelStrategy walk=new TravelStrategy(Strategy.WALK); walk.travel(); TravelStrategy plane=new TravelStrategy(Strategy.PLANE); plane.travel(); TravelStrategy subway=new TravelStrategy(Strategy.SUBWAY); subway.travel(); } }这样做有一个致命的缺点,一旦出行的方式要增加,我们就不得不增加新的else if语句,而这违反了面向对象的原则之一,对修改封闭。而这时候,策略模式则可以完美的解决这一切。
首先,需要定义一个策略接口。
public interface Strategy { void travel(); }然后根据不同的出行方式实行对应的接口
public class WalkStrategy implements Strategy{ @Override public void travel() { System.out.println(walk); } } public class PlaneStrategy implements Strategy{ @Override public void travel() { System.out.println(plane); } } public class SubwayStrategy implements Strategy{ @Override public void travel() { System.out.println(subway); } }此外还需要一个包装策略的类,并调用策略接口中的方法
public class TravelContext { Strategy strategy; public Strategy getStrategy() { return strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void travel() { if (strategy != null) { strategy.travel(); } } }测试一下代码
public class Main { public static void main(String[] args) { TravelContext travelContext=new TravelContext(); travelContext.setStrategy(new PlaneStrategy()); travelContext.travel(); travelContext.setStrategy(new WalkStrategy()); travelContext.travel(); travelContext.setStrategy(new SubwayStrategy()); travelContext.travel(); } }输出结果如下
plane
walk
subway
可以看到,应用了策略模式后,如果我们想增加新的出行方式,完全不必要修改现有的类,我们只需要实现策略接口即可,这就是面向对象中的对扩展开放准则。假设现在我们增加了一种自行车出行的方式。只需新增一个类即可。
public class BikeStrategy implements Strategy{ @Override public void travel() { System.out.println(bike); } }之后设置策略即可
public class Main { public static void main(String[] args) { TravelContext travelContext=new TravelContext(); travelContext.setStrategy(new BikeStrategy()); travelContext.travel(); } }而在Android的系统源码中,策略模式也是应用的相当广泛的.最典型的就是属性动画中的应用.
我们知道,在属性动画中,有一个东西叫做插值器,它的作用就是根据时间流逝的百分比来来计算出当前属性值改变的百分比.
我们使用属性动画的时候,可以通过set方法对插值器进行设置.可以看到内部维持了一个时间插值器的引用,并设置了getter和setter方法,默认情况下是先加速后减速的插值器,set方法如果传入的是null,则是线性插值器。而时间插值器TimeInterpolator是个接口,有一个接口继承了该接口,就是Interpolator这个接口,其作用是为了保持兼容
private static final TimeInterpolator sDefaultInterpolator = new AccelerateDecelerateInterpolator(); private TimeInterpolator mInterpolator = sDefaultInterpolator; @Override public void setInterpolator(TimeInterpolator value) { if (value != null) { mInterpolator = value; } else { mInterpolator = new LinearInterpolator(); } } @Override public TimeInterpolator getInterpolator() { return mInterpolator; } public interface Interpolator extends TimeInterpolator { // A new interface, TimeInterpolator, was introduced for the new android.animation // package. This older Interpolator interface extends TimeInterpolator so that users of // the new Animator-based animations can use either the old Interpolator implementations or // new classes that implement TimeInterpolator directly. }