Android设计模式--之策略模式

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

 

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

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

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

定义接口Interpolator:

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

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

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

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

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

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

posted @ 2013-06-09 14:13  zghbhdxw  阅读(177)  评论(0编辑  收藏  举报