欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

基于Android设计模式之--SDK源码之策略模式的详解

程序员文章站 2023-11-23 22:52:52
策略模式其实特别简单(听到这句话,大家是不是心里一下子放松了?)。比如排序,官方告诉大家我这里有一个排序的接口isort的sort()方法,然后民间各尽其能,实现这个排序的...

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

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

2. 结构图和代码
animation不同动画的实现,主要是依靠interpolator的不同实现而变。
基于Android设计模式之--SDK源码之策略模式的详解
定义接口interpolator:

复制代码 代码如下:

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为例,实现具体的策略,代码如下:
复制代码 代码如下:

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类是怎么做的:
复制代码 代码如下:

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方法,注释。配置解析等等