• 设计模式之策略模式


    策略模式其实特别简单(听到这句话,大家是不是心里一下子放松了?)。
    比如排序,官方告诉大家我这里有一个排序的接口ISort的sort()方法,然后民间各尽其能,实现这个排序的方法:冒泡,快速,堆等等。
    这些方法就是“不同的策略”。
    然后,某个模块下,需要一个排序方法,但是暂时不能指定具体的sort方法(出于扩展的考虑),就需要使用ISort接口了。
    最后,具体什么场景下,传入什么具体的sort方法,实现灵活的排序。
    这就是策略模式!
    下面,我们分析Android中的动画是如何使用策略模式的。

    1. 意图
    定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换。
    策略模式使得算法可独立于使用它的客户而变化。

    2. 结构图和代码
    Animation不同动画的实现,主要是依靠Interpolator的不同实现而变。

    定义接口Interpolator:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package android.animation;
     
    /**
     * A time interpolator defines the rate of change of an animation. This allows animations
     * to have non-linear motion, such as acceleration and deceleration.
     */
    public interface Interpolator {
     
        /**
         * Maps a value representing the elapsed fraction of an animation to a value that represents
         * the interpolated fraction. This interpolated value is then multiplied by the change in
         * value of an animation to derive the animated value at the current elapsed animation time.
         *
         * @param input A value between 0 and 1.0 indicating our current point
         *        in the animation where 0 represents the start and 1.0 represents
         *        the end
         * @return The interpolation value. This value can be more than 1.0 for
         *         interpolators which overshoot their targets, or less than 0 for
         *         interpolators that undershoot their targets.
         */
        float getInterpolation(float input);
    }

    我们以AccelerateInterpolator为例,实现具体的策略,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    package android.view.animation;
     
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.util.AttributeSet;
     
    /**
     * An interpolator where the rate of change starts out slowly and
     * and then accelerates.
     *
     */
    public class AccelerateInterpolator implements Interpolator {
        private final float mFactor;
        private final double mDoubleFactor;
     
        public AccelerateInterpolator() {
            mFactor = 1.0f;
            mDoubleFactor = 2.0;
        }
     
        /**
         * Constructor
         *
         * @param factor Degree to which the animation should be eased. Seting
         *        factor to 1.0f produces a y=x^2 parabola. Increasing factor above
         *        1.0f  exaggerates the ease-in effect (i.e., it starts even
         *        slower and ends evens faster)
         */
        public AccelerateInterpolator(float factor) {
            mFactor = factor;
            mDoubleFactor = 2 * mFactor;
        }
     
        public AccelerateInterpolator(Context context, AttributeSet attrs) {
            TypedArray a =
                context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AccelerateInterpolator);
     
            mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);
            mDoubleFactor = 2 * mFactor;
     
            a.recycle();
        }
     
        public float getInterpolation(float input) {
            if (mFactor == 1.0f) {
                return input * input;
            } else {
                return (float)Math.pow(input, mDoubleFactor);
            }
        }
    }

    其他的Interpolator实现在此不列举了。
    如何在Animation模块实现不同的动画呢?
    在这里我想提一个应用很广的概念:依赖注入。
    在Animation模块里实现不同的动画,就是需要我们把各个Interpolator以父类或者接口的形式注入进去。
    注入的方法一般是构造函数,set方法,注释等等。
    我们看看animation类是怎么做的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public abstract class Animation implements Cloneable {
        Interpolator mInterpolator;
        // 通过set方法注入   
        public void setInterpolator(Interpolator i) {
             mInterpolator = i;
         }
     
        public boolean getTransformation(long currentTime, Transformation outTransformation) {
            // ... ...
            // 具体调用
            final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
            applyTransformation(interpolatedTime, outTransformation);
           // ... ...
        }
     
         // 缺省实现,是个小技巧,顺便提下,这个不是重点
         protected void ensureInterpolator() {
             if (mInterpolator == null) {
                 mInterpolator = new AccelerateDecelerateInterpolator();
             }
         }
     
    }

      策略模式其实就是多态的一个淋漓精致的体现。

    3. 效果
    (1).行为型模式
    (2).消除了一些if...else...的条件语句
    (3).客户可以对实现进行选择,但是客户必须要了解这个不同策略的实现(这句话好像是废话,总而言之,客户需要学习成本)
    (4).代码注释中提到了缺省实现,可以让客户不了解策略,也能实现默认的策略
    (5).注入的方式有多种:构造函数,set方法,注释。配置解析等等

    本贴原址:http://www.cnblogs.com/qianxudetianxia/archive/2013/04/19/3030235.html

  • 相关阅读:
    1022 Digital Library (30 分)(map)
    1023 Have Fun with Numbers (20 分)(大整数运算)
    1019 General Palindromic Number (20 分)(回文数)
    Flink实时项目例程
    Spark Streaming+kafka+spring boot+elasticsearch实时项目(canal)
    Flink es-sink解决java.lang.NoSuchFieldError: FAIL_ON_SYMBOL_HASH_OVERFLOW
    Flink安装及WordCount实例yarn-cluster提交
    解决windows上The root scratch dir: /tmp/hive on HDFS should be writable.Current permissions are: ------
    RDD(弹性分布式数据集)介绍---Spark的核心
    Scala快速入门(零基础到入门)
  • 原文地址:https://www.cnblogs.com/hbxblogs/p/3416144.html
Copyright © 2020-2023  润新知