简介:实现某种功能可以有多种算法和策略,根据实际情况不同选择不同的算法。如排序,可以选择选择排序,冒泡排序,快速排序等,若在一个类中通过if else选择具体的算法(硬编码),类臃肿且维护成本高。因此需要将这些算法抽离出来,提供统一接口,对应不同算法的实现,就可以通过注入不同的对象来实现算法或者策略的动态替换,提高扩展性维护性,即策略模式。
定义:定义了一系列的算法并将其封装,使他们可以互相替换,策略模式让算法独立于使用它的客户而独立变化。
场景:①.针对同一类型问题的多种处理方式,仅仅是具体行为有差别时。
②.需要安全的封装多种同一类型的操作时。
③.出现同一抽象类有多个子类,而又需要使用if else或者switch case选择具体子类时。
关键点:Stragety--抽象策略
ConcreteStrage--具体的策略实现
Context--上下文操作类
使用:
//计算的策略
interface ICalculateStrategy{
//具体的计算方法
fun calculate(km:Int):String
}
//具体的算法实现 简单起见,直接返回String
class BusStrategy:ICalculateStrategy{
override fun calculate(km: Int):String{
return "Bus$km"
}
}
class CarStrategy:ICalculateStrategy{
override fun calculate(km: Int):String{
return "Car$km"
}
}
//实际操作类
class TrafficCalculator{
//代表策略
var mStrategy:ICalculateStrategy?=null
fun calculatePrice(km:Int){
mStrategy?.calculate(km)
}
}
companion object {
@JvmStatic
fun main(args: Array<String>) {
//实际的调用
val calculator = TrafficCalculator()
//选择策略
calculator.mStrategy = BusStrategy()
//计算
calculator.calculatePrice(20)
}
}
如Android中动画的使用,也用到了策略模式:
//View.java
public void startAnimation(Animation animation) {
//1.设置动画开始时间为-1
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
//2.对View设置动画
setAnimation(animation);
//3.刷新父类缓存
invalidateParentCaches();
//4.刷新View本身及子View
invalidate(true);
}
先设置动画的时间,再对View设置动画,最后向ViewGroup请求刷新视图,随后ViewGroup就会调用dispatchDraw()方法对这个View所在的区域进行重绘,对于某个View的重绘最终会调用ViewGroup中的drawChild(Canvas canvas,View child,long drawinngTime)方法。
//ViewGroup.java
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
return child.draw(canvas, this, drawingTime);
}
最终还是调用了View的draw方法
//View.java
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
//...
//查看是否需要清除动画信息
final int parentFlags = parent.mGroupFlags;
//获取动画
final Animation a = getAnimation();
if (a != null) {
//应用动画
more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
//...
}
}
private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
Animation a, boolean scalingRequired) {
Transformation invalidationTransform;
final int flags = parent.mGroupFlags;
final boolean initialized = a.isInitialized();
//是否初始化过,默认为false
if (!initialized) {
//初始化动画
a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
//动画监听回调
onAnimationStart();
}
//获取Transformation 存储动画信息
final Transformation t = parent.getChildTransformation();
//通过计算获取动画相关值
boolean more = a.getTransformation(drawingTime, t, 1f);
//...
if (more) {
//根据具体实现,判断当前动画类型是否需要调整位置大小,刷新不同区域
if (!a.willChangeBounds()) {
//...
} else {
//获取重绘区域
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;
}
//Animation.java 通过计算获取动画相关值
public boolean getTransformation(long currentTime, Transformation outTransformation) {
//在最开始startAnimation时改值设为了-1
if (mStartTime == -1) {
mStartTime = currentTime;
}
//计算时间流逝的百分比
final long startOffset = getStartOffset();
final long duration = mDuration;
float normalizedTime;
if (duration != 0) {
normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /
(float) duration;
} else {
normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
}
//计算动画是否已完成
final boolean expired = normalizedTime >= 1.0f || isCanceled();
mMore = !expired;
//...
if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {
if (!mStarted) {
fireAnimationStart();
mStarted = true;
}
//通过插值器获取动画执行百分比
final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
//应用动画效果
applyTransformation(interpolatedTime, outTransformation);
}
//动画执行完毕,出发完成或者重复的回调
if (expired) {
if (mRepeatCount == mRepeated || isCanceled()) {
if (!mEnded) {
mEnded = true;
guard.close();
fireAnimationEnd();
}
} else {
if (mRepeatCount > 0) {
mRepeated++;
}
if (mRepeatMode == REVERSE) {
mCycleFlip = !mCycleFlip;
}
mStartTime = -1;
mMore = true;
fireAnimationRepeat();
}
}
if (!mMore && mOneMoreTime) {
mOneMoreTime = false;
return true;
}
return mMore;
}
//触发动画的回调
private void fireAnimationStart() {
if (mListener != null) {
if (mListenerHandler == null) mListener.onAnimationStart(this);
else mListenerHandler.postAtFrontOfQueue(mOnStart);
}
}
这是LinearInterpolator ,就返回当前的进度:
public class LinearInterpolator extends BaseInterpolator {
//...
public float getInterpolation(float input) {
return input;
}
}
在Animation的applyTransformation方法里,是一个protected 空实现,因此看它的子类实现,如ScaleAnimator
//Animation.java
protected void applyTransformation(float interpolatedTime, Transformation t) {
}
//ScaleAnimator.java
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float sx = 1.0f;
float sy = 1.0f;
float scale = getScaleFactor();
if (mFromX != 1.0f || mToX != 1.0f) {
sx = mFromX + ((mToX - mFromX) * interpolatedTime);
}
if (mFromY != 1.0f || mToY != 1.0f) {
sy = mFromY + ((mToY - mFromY) * interpolatedTime);
}
//最终通过Matrix实现对View的缩放
if (mPivotX == 0 && mPivotY == 0) {
t.getMatrix().setScale(sx, sy);
} else {
t.getMatrix().setScale(sx, sy, scale * mPivotX, scale * mPivotY);
}
}
接下来分析下ObjectAnimator
//这是简单的使用
ObjectAnimator.ofFloat(tv,"translationX",0f,10f,100f).start()
//ObjectAnimator.java
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
//1.新建ObjectAnimator
ObjectAnimator anim = new ObjectAnimator(target, propertyName);
//2.给Anim设置值
anim.setFloatValues(values);
return anim;
}
//构造器就做了两件事,设置了动画对象mTarget及属性
private ObjectAnimator(Object target, String propertyName) {
setTarget(target);
setPropertyName(propertyName);
}
@Override
public void setTarget(@Nullable Object target) {
final Object oldTarget = getTarget();
if (oldTarget != target) {
if (isStarted()) {
cancel();
}
//赋值mTarget
mTarget = target == null ? null : new WeakReference<Object>(target);
//标志位
mInitialized = false;
}
}
public void setPropertyName(@NonNull String propertyName) {
//mValues PropertyValuesHolder是父ValueAnimator的属性第一次为null
if (mValues != null) {
//缓存
PropertyValuesHolder valuesHolder = mValues[0];
String oldName = valuesHolder.getPropertyName();
valuesHolder.setPropertyName(propertyName);
mValuesMap.remove(oldName);
mValuesMap.put(propertyName, valuesHolder);
}
//赋值属性名
mPropertyName = propertyName;
mInitialized = false;
}
//接下来是setFloatValues
@Override
public void setFloatValues(float... values) {
//第一次为null,mProperty 也为null
if (mValues == null || mValues.length == 0) {
if (mProperty != null) {
setValues(PropertyValuesHolder.ofFloat(mProperty, values));
} else {
//走到这,1.PropertyValuesHolder 2.setValues
setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
}
} else {
super.setFloatValues(values);
}
}
//先看PropertyValuesHolder.java
public static PropertyValuesHolder ofFloat(String propertyName, float... values) {
return new FloatPropertyValuesHolder(propertyName, values);
}
//内部类FloatPropertyValuesHolder继承PropertyValuesHolder
public FloatPropertyValuesHolder(String propertyName, float... values) {
//调用PropertyValuesHolder设置了mPropertyName
super(propertyName);
//设置目标属性值
setFloatValues(values);
}
@Override
public void setFloatValues(float... values) {
//调用父类PropertyValuesHolder.setFloatValues
super.setFloatValues(values);
//转为FloatKeyframes 获取动画关键帧
mFloatKeyframes = (Keyframes.FloatKeyframes) mKeyframes;
}
//PropertyValuesHolder的方法
public void setFloatValues(float... values) {
//设置value的type和KeyframeSet
mValueType = float.class;
//根据values创建KeyframeSet(保存每个时刻该属性对应的值)
mKeyframes = KeyframeSet.ofFloat(values);
}
public static KeyframeSet ofFloat(float... values) {
//根据values创建FloatKeyframe数组
//保存每个时刻该属性对应的值
int numKeyframes = values.length;
FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)];
new FloatKeyframe设置百分比及valueType float.class
if (numKeyframes == 1) {
keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f);
keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]);
} else {
keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]);
for (int i = 1; i < numKeyframes; ++i) {
keyframes[i] =
(FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);
}
}
//这些keyframes转为FloatKeyframeSet,最终调用父类构造方法
return new FloatKeyframeSet(keyframes);
}
//KeyframeSet.java
public KeyframeSet(Keyframe... keyframes) {
mNumKeyframes = keyframes.length;
mKeyframes = Arrays.asList(keyframes);
mFirstKeyframe = keyframes[0];
mLastKeyframe = keyframes[mNumKeyframes - 1];
mInterpolator = mLastKeyframe.getInterpolator();
}
//最后是setValues
public void setValues(PropertyValuesHolder... values) {
int numValues = values.length;
//赋值mValues PropertyValuesHolder,后面会用到
mValues = values;
//新建集合保存PropertyName和PropertyValuesHolder
mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
for (int i = 0; i < numValues; ++i) {
PropertyValuesHolder valuesHolder = values[i];
mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
}
mInitialized = false;
}
PropertyValuesHolder是属性和属性值的辅助类,保存了属性的名称,get set方法以及该属性在duration内各个时刻对应属性的值(mKeyframes),执行动画时,只需要根据动画的执行时间,到mKeyframes中查询该时刻对应的属性值,然后修改执行动画的对象的目标属性,连续过程即可达到动画的效果。
接下来,我们看看ObjectAnimator的start()。
//ObjectAnimator.java
@Override
public void start() {
//...调用父类ValueAnimator.java
super.start();
}
//ValueAnimator.java
@Override
public void start() {
start(false);
}
private void start(boolean playBackwards) {
//主线程
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
mReversing = playBackwards;
mSelfPulse = !mSuppressSelfPulseRequested;
//循环动画的计算
if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
if (mRepeatCount == INFINITE) {
float fraction = (float) (mSeekFraction - Math.floor(mSeekFraction));
mSeekFraction = 1 - fraction;
} else {
mSeekFraction = 1 + mRepeatCount - mSeekFraction;
}
}
//一些状态
mStarted = true;
mPaused = false;
mRunning = false;
mAnimationEndRequested = false;
mLastFrameTime = -1;
mFirstFrameTime = -1;
mStartTime = -1;
addAnimationCallback(0);
//mStartDelay 默认0
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
//通知监听onAnimationStart()
startAnimation();
//根据mSeekFraction 进度来判断
if (mSeekFraction == -1) {
setCurrentPlayTime(0);
} else {
setCurrentFraction(mSeekFraction);
}
}
}
public void setCurrentPlayTime(long playTime) {
//根据时长获取fraction 比例
float fraction = mDuration > 0 ? (float) playTime / mDuration : 1;
setCurrentFraction(fraction);
}
public void setCurrentFraction(float fraction) {
initAnimation();
fraction = clampFraction(fraction);
mStartTimeCommitted = true;
if (isPulsingInternal()) {
long seekTime = (long) (getScaledDuration() * fraction);
long currentTime = AnimationUtils.currentAnimationTimeMillis();
mStartTime = currentTime - seekTime;
} else {
mSeekFraction = fraction;
}
mOverallFraction = fraction;
final float currentIterationFraction = getCurrentIterationFraction(fraction, mReversing);
//这里是真正改变的方法
animateValue(currentIterationFraction);
}
//这是ValueAnimator.java中的方法
void animateValue(float fraction) {
fraction = mInterpolator.getInterpolation(fraction);
mCurrentFraction = fraction;
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
//PropertyValuesHolder[] mValues;
mValues[i].calculateValue(fraction);
}
if (mUpdateListeners != null) {
int numListeners = mUpdateListeners.size();
for (int i = 0; i < numListeners; ++i) {
//触发onAnimationUpdate回调
mUpdateListeners.get(i).onAnimationUpdate(this);
}
}
}
//FloatPropertyValuesHolder的实现,获取对应属性值
@Override
void calculateValue(float fraction) {
mFloatAnimatedValue = mFloatKeyframes.getFloatValue(fraction);
}
走到这发现已经走不下去了,我们可以回过头看看,是不是少了点什么,因为具体的修改target的方法根本没有看到,因此这里animateValue是ValueAnimator.java的方法,我们找下ObjectAnimator里:
//ObjectAnimator.java
@CallSuper
@Override
void animateValue(float fraction) {
final Object target = getTarget();
//判空
if (mTarget != null && target == null) {
cancel();
return;
}
//执行上面父animateValue的操作
super.animateValue(fraction);
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
//所以实际操作应该在这里mValues = PropertyValuesHolder
//所以找FloatPropertyValuesHolder里的这个方法
mValues[i].setAnimatedValue(target);
}
}
//FloatPropertyValuesHolder是PropertyValuesHolder内部类
@Override
void setAnimatedValue(Object target) {
//如果有floatProperty,通过setValue修改
//比如修改scaleX,这个Property为floatProperty,则直接执行这里
if (mFloatProperty != null) {
mFloatProperty.setValue(target, mFloatAnimatedValue);
return;
}
//如果有属性,通过set来更新
if (mProperty != null) {
mProperty.set(target, mFloatAnimatedValue);
return;
}
if (mSetter != null) {
try {
mTmpValueArray[0] = mFloatAnimatedValue;
//其他的set方法通过反射调用target的set方法
mSetter.invoke(target, mTmpValueArray);
} catch (InvocationTargetException e) {
}
}
}
总结:
优:结构清晰,使用简单直观,耦合度低,扩展方便,操作封装彻底,数据更为安全
缺:随着策略增加,子类变多。