设计模式(三)Animation中的策略模式

栏目: 后端 · 发布时间: 5年前

内容简介:定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变换。算法过多会造成多个算法实现类。Context需要了解所有的算法,并做出相应的调用。例如租房可以通过各种途径,包括中介、房东、朋友等。每一种途径都可以当成一种策略,可以互相切换。

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

2、类图:

设计模式(三)Animation中的策略模式
  • Context对象: 封装可能存在的策略变化,屏蔽其他模块对算法的直接访问
  • Stategy抽象策略:定义通用算法规则
  • ConcreteStategy具体策略:含有具体的算法

3、应用场景:

  • 对调用者隐藏算法具体实现细节
  • 针对同一问题有多种处理方式,需要通过if else等形式选择某一种方式

4、优点:

  • 避免多种处理方式存在的if else语句。方便拓展,多一种处理方式,就多加一个实现类
  • 结构比较清晰,封装性更好

5、缺点:

算法过多会造成多个算法实现类。Context需要了解所有的算法,并做出相应的调用。

二、实例:

例如租房可以通过各种途径,包括中介、房东、朋友等。每一种途径都可以当成一种策略,可以互相切换。

1、抽象策略:

public interface RentingStrategy {
    void renting();
}
复制代码

2、具体策略

中介:

public class AgencyStrategy implements RentingStrategy {
    @Override
    public void renting() {
        System.out.println("通过中介租房");
    }
}
复制代码

房东:

public class LandlordStrategy implements RentingStrategy {
    @Override
    public void renting() {
        System.out.println("通过房东租房");
    }
}
复制代码

朋友:

public class FriendStrategy implements RentingStrategy {
    @Override
    public void renting() {
        System.out.println("通过朋友租房");
    }
}
复制代码

3、Context

public class Context {
    private RentingStrategy mRentingStrategy;

    public Context(RentingStrategy rentingStrategy) {
        this.mRentingStrategy = rentingStrategy;
    }

    public void rentHouse() {
        this.mRentingStrategy.renting();
    }
}
复制代码

4、调用

public class StrategyTest{
    public static void main(String[] args) {
        RentingStrategy friendStrategy = new FriendStrategy();
        Context context = new Context(friendStrategy);
        context.rentHouse();
    }
}
复制代码

三、动画插值器

动画插值器的作用就是根据时间流逝的百分比来来计算出当前属性值改变的百分比。比如LinearInterpolator用于匀速动画、AccelerateDecelerateInterpolator用于加速减速动画等等。

设计模式(三)Animation中的策略模式

1、Interpolator

public interface Interpolator extends TimeInterpolator { }

public interface TimeInterpolator {

    /**
     * 返回流逝时间的百分比
     */
    float getInterpolation(float input);
}
复制代码

定义接口和策略可提供的方法

2、LinearInterpolator

@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

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

}
复制代码

3、AccelerateDecelerateInterpolator

@HasNativeInterpolator
public class AccelerateDecelerateInterpolator extends BaseInterpolator
        implements NativeInterpolatorFactory {
    public AccelerateDecelerateInterpolator() {
    }

    @SuppressWarnings({"UnusedDeclaration"})
    public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
    }
    
}
复制代码

不同的插值器区别在于getInterpolation返回值不同,也就是说算法不同。

4、插值器调用

(1)setInterpolator设置插值器

#Animation
public void setInterpolator(Interpolator i) {
    mInterpolator = i;
}
复制代码

通过setInterpolator设置某个插值器(某种策略)

(2)View的startAnimation

#View
public void startAnimation(Animation animation) {
    animation.setStartTime(Animation.START_ON_FIRST_FRAME);
    //设置动画
    setAnimation(animation);
    //刷新父类缓存
    invalidateParentCaches();
    //刷新View跟子View
    invalidate(true);
}
复制代码

invalidate会对View进行重绘,调用View的draw方法

(3)draw

boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
    ......
    final Animation a = getAnimation();
    if (a != null) {
        more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
        ......
    }
}
复制代码
private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
        Animation a, boolean scalingRequired) {
        ......
        //设置动画开始监听
        onAnimationStart();
    }

        ......
        invalidationTransform = parent.mInvalidationTransformation;
        //获取到动画的相关值
        a.getTransformation(drawingTime, invalidationTransform, 1f);
    } else {
        invalidationTransform = t;
    }

    if (more) {
            ......
            // 获取重绘的区域
            final RectF region = parent.mInvalidateRegion;
            a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
                    invalidationTransform);

            parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
            // 重新计算区域
            final int left = mLeft + (int) region.left;
            final int top = mTop + (int) region.top;
            // 进行更新
            parent.invalidate(left, top, left + (int) (region.width() + .5f),
                    top + (int) (region.height() + .5f));
        }
    }
    return more;
}
复制代码

(4)Animation.getTransformation

里面实现了动画的具体值的改变

public boolean getTransformation(long currentTime, Transformation outTransformation) {
    ......
        //通过插值器获取动画执行百分比
        final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
        applyTransformation(interpolatedTime, outTransformation);
    }
    ......

    return mMore;
}

复制代码

内部通过调用Interpolator的getInterpolation方法来获取动画执行百分比


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

高扩展性网站的50条原则

高扩展性网站的50条原则

[美] Martin L. Abbott、[美]Michael T. Fisher / 张欣、杨海玲 / 人民邮电出版社 / 2012-6-3 / 35.00元

《高扩展性网站的50条原则》给出了设计高扩展网站的50条原则,如不要过度设计、设计时就考虑扩展性、把方案简化3倍以上、减少DNS查找、尽可能减少对象等,每个原则都与不同的主题绑定在一起。大部分原则是面向技术的,只有少量原则解决的是与关键习惯和方法有关的问题,当然,每个原则都对构建可扩展的产品至关重要。 主要内容包括: 通过克隆、复制、分离功能和拆分数据集提高网站扩展性; 采用横向......一起来看看 《高扩展性网站的50条原则》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试