设计模式-策略模式(基于Android属性动画插值器学习)

353 阅读4分钟

策略模式定义:

以编码角度来看,就是将算法处理逻辑单独封装成一个策略,根据问题类型的不同,选择对应的策略来处理,所以说策略模式中的策略也就是算法逻辑,当你将算法逻辑封装成方法(函数)或是具体的实现类的时候,这个方法或类就可以说是一个策略。那么具体怎么使用该模式,下面将以Android开发中属性动画的插值器的实现方式作为示例,来学习策略模式。

代码示例分析(Android属性动画插值器Interpolator)

public interface TimeInterpolator {
    float getInterpolation(float input);
}

//插值器接口,没有变量和方法
public interface Interpolator extends TimeInterpolator {
    
}

//BaseInterpolator实现Interpolator接口
abstract public class BaseInterpolator implements Interpolator {

    private @Config int mChangingConfiguration;
    
    public @Config int getChangingConfiguration() {
        return mChangingConfiguration;
    }

    void setChangingConfiguration(@Config int changingConfiguration) {
        mChangingConfiguration = changingConfiguration;
    }
}

//接着就是我们能常用的抽象类的具体实现类,以LinearInterpolator为例:

//看一下作用于动画匀速运动的LinearInterpolator插值器的源码:
@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolator {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

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

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactory.createLinearInterpolator();
    }
}
//内置的插值器有多种,比如:DecelerateInterpolator(减速插值器)、CycleInterpolator(周期运动插值器)等,
//属性动画的常规用法如下:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(textView,"translationX", 0,100);
objectAnimator.setDuration(5000);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();

这里的objectAnimator.setInterpolator(new LinearInterpolator())方法,将LinearInterpolator实例复制到objectAnimator实例中的 mInterpolator成员变量,而该成员变量是TimeInterpolator类型的,objectAnimator最终会在animateValue中调用getInterpolation方法。

void animateValue(float fraction) {
    fraction = mInterpolator.getInterpolation(fraction);
    mCurrentFraction = fraction;
    int numValues = mValues.length;
    for (int i = 0; i < numValues; ++i) {
        mValues[i].calculateValue(fraction);
    }
    if (mUpdateListeners != null) {
        int numListeners = mUpdateListeners.size();
        for (int i = 0; i < numListeners; ++i) {
            mUpdateListeners.get(i).onAnimationUpdate(this);
        }
    }
}

根据多态性,这里的getInterpolation()方法被调用时,会执行的是在对ObjectAnimator实例设置插值器时的LinearInterpolator实例的getInterpolation()方法逻辑代码,这样就可以实现给objectAnimator设置不同的插值器时,执行不同的算法逻辑,达到不同的动画效果。并且可以仿照LinearInterpolator实现自定义插值器,大概思路就是:

创建CustomInterpolator继承自BaseInterpolator 或是实现Interpolator接口

public class CustomInterpolator extends BaseInterpolator implements NativeInterpolator{
    //这里主要重写该方法
    public float getInterpolation(float input) {
        //实现自定义算法逻辑
        return input;
    }
}

//通过该objectAnimator.setInterpolator(new CustomInterpolator());
//方法将自定义插值器CustomInterpolator设置到属性动画实例即可

自定义Interpolator实现方法也比较简单,到了这里就可以发现通过这种方法就可以对Interpolator进行扩展,对原有代码没有任何影响,便于程序的扩展。

总结

所以策略模式的整体思路如图:

策略模式UML.png 具体代码实现思路:

//定义策略接口
public interface Strategy { 
    public int method(); 
}

//创建策略接口实现类(这里模拟实现两种不同策略)
public class StrategyImpl1 Strategy implements Strategy { 
    @Override 
    public int method() { 
        //这里实现不同的算法
        return xxx; 
    } 
}
public class StrategyImpl2 Strategy implements Strategy { 
    @Override 
    public int method() { 
        //这里实现不同的算法
        return xxx; 
    } 
}

//需要使用不同策略的实体类(使用策略者)
public class PolicyUser { 
    private Strategy strategy; 
    public PolicyUser(Strategy strategy){ 
        this.strategy = strategy; 
    } 
    public int method(){ 
        return strategy.method(); 
    } 
}

//具体策略使用者调用策略的一般情形
public class StrategyDemo { 
    public static void main(String[] args) { 
    
           PolicyUser policyUser = new PolicyUser(new StrategyImpl1()); 
           policyUser.method();//这里执行的会是StrategyImpl1类中的method()方法
           
           PolicyUser policyUser = new PolicyUser(new StrategyImpl2()); 
           policyUser.method();//这里执行的会是StrategyImpl2类中的method()方法
           
    }
}

即是将逻辑处理方法封装成方法,创建策略接口并定义策略方法,接着可以创建具体的实现类,又或是创建抽象类(因为这样在一个策略分为多个算法时更方便于后续扩展)。

在这里的策略一般做法都是将其封装成类(这样做比分装成方法更便于扩展),所以每当需要增加一种策略时就需定义一个策略类,所以其缺点也就是当有大量策略时会需要大量的策略算法实现类。所以应根据实际情况使用相应的策略,比如只需一两个条件判断就可以选择不同策略应对不同情况的时候,并且无需过多考虑扩展性的时候,就不必强行使用策略模式了。