前言

定义:定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

使用场景:

  • 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
  • 需要安全地封装多种同一类型的操作时;
  • 出现同一抽象类有多个子类,而又需要使用if-else或者switch-case来选择具体子类时;

UML类图:

android trace 打不开_设计模式

实现示例

这里我们以乘坐不同的交通工具计算费用来举例:

  1. 乘坐地铁,6公里内(3元),6~12公里(4元),其他都算6元;
  2. 乘坐公交车,一条线路,上车都是3元;
  3. 乘坐Taxi,10公里内10元,超出每公里3元;

我们使用策略模式来实现:

  • 首先,定义计算价格策略接口,IStrategy
interface IStrategy {
    fun calculatePrice(km: Int): Int
}
  • 公交车价格计算策略,BusStrategy;
class BusStrategy : IStrategy {
    override fun calculatePrice(km: Int): Int {
        return 3
    }
}
  • 地铁价格计算策略,SubwayStrategy;
class SubwayStrategy : IStrategy {
    override fun calculatePrice(km: Int): Int {
        if (km <= 6) {
            return 3
        }
        if (km <= 12) {
            return 4
        }
        return 6
    }
}
  • Taxi价格计算策略,TaxiStrategy;
class TaxiStrategy : IStrategy {
    override fun calculatePrice(km: Int): Int {
        if (km < 10) {
            return 10
        }
        return (km - 10) * 3 + 10
    }
}
  • 测试类;
object Test {

    @JvmStatic
    fun main(args: Array<String>) {
        //公交车计算
        val busStrategy = ContextStrategy(BusStrategy())
       println(busStrategy.calculatePrice(10))

        //Taxi计算
        val taxiStrategy = ContextStrategy(TaxiStrategy()) //只需要替换具体实现,满足里氏替换原则
        println(taxiStrategy.calculatePrice(10))
    }
}

Android源码中的策略模式

  • 动画Interpolator(差值器) 我们分析下源码:我们常用的LinearInterpolator(线性差值器)AccelerateInterpolator(加速差值器)DecelerateInterpolator(减速差值器)继承BaseInterpolator,BaseInterpolator 实现Interpolator接口,而Interpolator又继承于TimeInterpolator接口,相关源码如下:
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolator {
    public LinearInterpolator() {
    }
    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

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

    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactory.createLinearInterpolator();
    }
}
abstract public class BaseInterpolator implements Interpolator {
    private @Config int mChangingConfiguration;
    /**
     * @hide
     */
    public @Config int getChangingConfiguration() {
        return mChangingConfiguration;
    }

    /**
     * @hide
     */
    void setChangingConfiguration(@Config int changingConfiguration) {
        mChangingConfiguration = changingConfiguration;
    }
}
public interface Interpolator extends TimeInterpolator {
package android.animation;

public interface TimeInterpolator {

    float getInterpolation(float input);
}

我们在看下ValueAnimator中设置差值器以及调用getInterpolation方法的源码

public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
 .....
    @Override
    public void setInterpolator(TimeInterpolator value) {
        if (value != null) {
            mInterpolator = value;
        } else {
            mInterpolator = new LinearInterpolator();
        }
    }
}
	获取差值器的值不断更新动画
    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);
            }
        }
    }
    ....

结合策略模式UML我们来整理下Interpolator相关的UML图:

android trace 打不开_设计模式_02


是不是就是就是很典型的策略模式

总结

策略模式主要用来分离算法,在相同的行为抽象下有不同的具体实现策略。
这个模式很好地演示了开闭原则,也就是定义抽象,注入不同的实现,而从达到很好的可扩展性。

优点:

  • 结构清晰明了、使用简单直观;
  • 耦合度较低,扩展方便;
  • 操作封装彻底,数据更为安全;

缺点:

  • 随着策略的增加,子类也变得繁多。

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )