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


/**
 * 这样做有一个致命的缺点,一旦出行的方式要增加,
 * 我们就不得不增加新的else if语句,而这违反了面向对象的原则之一,
 * 对修改封闭。而这时候,策略模式则可以完美的解决这一切。
 */
public static void testNormol() {
    TravelStrategy walk=new TravelStrategy(TravelStrategy.Strategy.WALK);
    walk.travel();

    TravelStrategy plane=new TravelStrategy(TravelStrategy.Strategy.PLANE);
    plane.travel();

    TravelStrategy subway=new TravelStrategy(TravelStrategy.Strategy.SUBWAY);
    subway.travel();
}




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);
    }


}



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


采用策略模式如下:


/**
 * 可以看到,应用了策略模式后,如果我们想增加新的出行方式,
 * 完全不必要修改现有的类,我们只需要实现策略接口即可,
 * 这就是面向对象中的对扩展开放准则。
 * 假设现在我们增加了一种自行车出行的方式。只需新增一个类即可。
 */
public static void testStrategy(){
    TravelContext travelContext=new TravelContext();
    travelContext.setStrategy(new PlaneStrategy());
    travelContext.travel();
    travelContext.setStrategy(new WalkStrategy());
    travelContext.travel();
    travelContext.setStrategy(new SubwayStrategy());
    travelContext.travel();
}


/**
 * Created by Administrator on 2017/9/15.
 */

public interface Strategy {

    void travel();

}


/**
 * Created by Administrator on 2017/9/15.
 */

public class PlaneStrategy implements Strategy {

    @Override
    public void travel() {
        Log.d("PlaneStrategy","travel");
    }
}


/**
 * Created by Administrator on 2017/9/15.
 */

public class SubwayStrategy implements Strategy {


    @Override
    public void travel() {
        Log.d("SubwayStrategy","travel");
    }
}


/**
 * Created by Administrator on 2017/9/15.
 */

public class WalkStrategy implements Strategy{


    @Override
    public void travel() {
        Log.d("WalkStrategy","travel");
    }
}


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();
        }
    }


}



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


总结:


策略模式:


1.它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。


 2.多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。 


 3.对客户隐藏具体策略(算法)的实现细节,彼此完全独立。


步骤:


1.定义了一个接口


2.一些具体的实现类,实现借口


3.一个中转类,处理策略,选择哪种策略




下面,我们分析Android中的动画是如何使用策略模式的。

而在Android的系统源码中,策略模式也是应用的相当广泛的.最典型的就是属性动画中的应用.


在属性动画中,有一个东西叫做插值器,它的作用就是根据时间流逝的百分比来来计算出当前属性值改变的百分比.






平时我们使用的时候,通过设置不同的插值器,实现不同的动画速率变换效果,



比如线性变换,回弹,自由落体等等。这些都是插值器接口的具体实现,也就是具体的插值器策略。我们略微来看几个策略。



private Interpolator line = new LinearInterpolator();// 线性
private Interpolator acc = new AccelerateInterpolator();// 加速
private Interpolator dce = new DecelerateInterpolator();// 减速
private Interpolator accdec = new AccelerateDecelerateInterpolator();// 先加速后减速



public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return input;
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createLinearInterpolator();
    }
}