策略模式实现与研究 - bei1999/work GitHub Wiki
定义
个人觉得策略模式可以用这个公式:不同的XXX 拥有不同的XXX供用户选择。
场景模拟
最近在做自定义时钟,遇到一个需求,时钟的样式可以定义几种,比如指针类型的,比如自定义的样式的,或者是纯数字的形式.
实现
- 不用任何模式实现
/**
* Created by lzb on 2017/12/6.
*/
public class WatchViewImpl02 extends View {
private int clockType;
enum Strategy{
DEFAULT,DESIGN,NROMAL
}
private Strategy strategy;
public WatchViewImpl02(Context context) {
super(context);
}
public WatchViewImpl02(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public WatchViewImpl02(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setIClockStrategy(Strategy Strategy) {
this.strategy = Strategy;
}
/**
* 开始绘制钟表
* @param canvas
*/
public void paint(Canvas canvas) {
if(strategy==Strategy.DEFAULT){
//
}else if(strategy==Strategy.DESIGN){
//
}else if(strategy==Strategy.NROMAL){
//
}
}
}
- 使用策略模式的实现 定义时钟接口
/**
* 定义时钟接口
*/
public interface IClock {
void paint(Canvas canvas);
}
/**
* 时钟接口实现类
*/
public class DefaultClockImpl implements IClock {
@Override
public void paint(Canvas canvas) {
}
}
/**
* 设计的时钟样式类
*/
public class DesignClockImpl implements IClock {
@Override
public void paint(Canvas canvas) {
}
}
/**
* 普通的时钟样式类(数字形式)
*/
public class NormalClockImpl implements IClock {
@Override
public void paint(Canvas canvas) {
}
}
/**
* 手表的时钟样式类(指针表示)
*/
public class WatchViewImpl extends View {
private IClock iClock;
public WatchViewImpl(Context context) {
super(context);
}
public WatchViewImpl(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public WatchViewImpl(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setIClock(IClock iClock) {
this.iClock = iClock;
}
/**
* 开始绘制钟表
* @param canvas
*/
public void paint(Canvas canvas) {
iClock.paint(canvas);
}
}
/**
* 客户端测试
*
* @author lzb
*/
public class WatchActivity extends Activity {
private WatchViewImpl watchView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_watch);
watchView = (WatchViewImpl) findViewById(R.id.watchview);
IClock defaultClock = new DefaultClockImpl();
IClock designClock = new DesignClockImpl();
IClock normalClock = new NormalClockImpl();
watchView.setIClock(defaultClock);
}
}
小结
从上面可以看出,如果我想定义这么多种样式用抽象类和接口肯定要copy一些重复的代码修改,多加if ..else 并且代码全部塞进了一个类中,有点混乱,这个时候用策略模式很好的解决了。
android 中的应用
安卓系统中策略模式也是应用的相当广泛的.最典型的就是属性动画中的应用,比如Interpolator类
//定义了一个差值器接口
public interface TimeInterpolator {
/**
* 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);
}
public interface Interpolator extends TimeInterpolator {
// A new interface, TimeInterpolator, was introduced for the new android.animation
// package. This older Interpolator interface extends TimeInterpolator so that users of
// the new Animator-based animations can use either the old Interpolator implementations or
// new classes that implement TimeInterpolator directly.
}
//抽象类实现了这个接口
/**
* An abstract class which is extended by default interpolators.
*/
abstract public class BaseInterpolator implements Interpolator {
private int mChangingConfiguration;
/**
* @hide
*/
public int getChangingConfiguration() {
return mChangingConfiguration;
}
/**
* @hide
*/
void setChangingConfiguration(int changingConfiguration) {
mChangingConfiguration = changingConfiguration;
}
}
//最后的不同样式实现
/**
* An interpolator where the rate of change starts and ends slowly but
* accelerates through the middle.
*/
@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;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();
}
}
//另外一种样式的实现
/**
* Repeats the animation for a specified number of cycles. The
* rate of change follows a sinusoidal pattern.
*
*/
@HasNativeInterpolator
public class CycleInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
public CycleInterpolator(float cycles) {
mCycles = cycles;
}
public CycleInterpolator(Context context, AttributeSet attrs) {
this(context.getResources(), context.getTheme(), attrs);
}
/** @hide */
public CycleInterpolator(Resources resources, Theme theme, AttributeSet attrs) {
TypedArray a;
if (theme != null) {
a = theme.obtainStyledAttributes(attrs, R.styleable.CycleInterpolator, 0, 0);
} else {
a = resources.obtainAttributes(attrs, R.styleable.CycleInterpolator);
}
mCycles = a.getFloat(R.styleable.CycleInterpolator_cycles, 1.0f);
setChangingConfiguration(a.getChangingConfigurations());
a.recycle();
}
public float getInterpolation(float input) {
return (float)(Math.sin(2 * mCycles * Math.PI * input));
}
private float mCycles;
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createCycleInterpolator(mCycles);
}
}
总结
android 系统源码中策略模式随处可见,除了上面的属性动画差值器外,listview 的adapter,viewpager的提供几个Indicator接口的实现类,都是类似的的原理。