策略模式
定义:
策略模式定义了一系列算法,并将每一个算法封装起来,而且使他们还可以相互转换。策略模式让算法独立于使用它的客户端而独立变化
实用场景
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时
- 需要安全的封装多种同一类型的操作时
- 出现同一抽象类有多个子类时,而又需要使用条件分支语句来选择具体子类时
策略模式的写法
UML图如下:
- Context:用来操作策略模式的上下文环境
- Stragety:策略的抽象
- ConcreteStragety:具体的策略实现
我们以打车计费来算,各种不同的车,其收费算法是不一样的,比如说公交车、出租车、地铁三种类型来说明,体现在在代码中就是条件语句判断车型,然后调用不同的计费算法,通常采用的方法是将这所有的算法封装到一个类中供统一调用,但是这种方法违反了开闭原则,使维护变得麻烦,比方说新添加一个车型,此时还要在类中加一条分支判断。所以这里考虑将各种计费方式分离开来
定义策略接口: Stragety
public interface CalculateStrategy {
//按距离计费
int calculatePrice(int km);
}
创建具体策略:
public class BusStrategy implements CalculateStrategy {
/**
* 公交车,十公里内一元,超过十公里,每加一元可乘5公里
* @param km
* @return
*/
@Override
public int calculatePrice(int km) {
int extraTotal = km - 10;
int extraFactor = extraTotal / 5;
int fraction = extraTotal % 5;
int price = 1 + extraFactor * 1;
return price;
}
}
public class SubwayStrategy implements CalculateStrategy {
/**
* 地铁:6公里内3元,6--12公里内4元,12--22内5元,其余简化为6元
* @param km
* @return
*/
@Override
public int calculatePrice(int km) {
if (km <= 6) {
return 3;
} else if(km > 6 && km <= 12) {
return 4;
} else if(km > 12 && km <= 22) {
return 5;
} else {
return 6;
}
}
}
创建Context:计价器
public class TranficCalculator {
private CalculateStrategy calculateStrategy;
public static void main(String[] args) {
TranficCalculator calculator = new TranficCalculator();
//设置计算策略
calculator.setCalculateStrategy(new BusStrategy());
//计算价格
System.out.println("公交车16公里价格:"+calculator.calculatePrice(16));
}
public void setCalculateStrategy (CalculateStrategy calculateStrategy){
this.calculateStrategy = calculateStrategy;
}
public int calculatePrice(int km) {
return calculateStrategy.calculatePrice(km);
}
}
时间差值器
根据时间流逝的百分比来计算当前属性值的改变百分比。常见的作用是动画开始时用于加速,结束时用于减速。系统预置的有线性插值器,加速插值器,减速插值器。
UML图如下:
Stragety : 抽象策略 BaseInterpolator
abstract public class BaseInterpolator implements Interpolator {
private int mChangingConfiguration;
public int getChangingConfiguration() {
return mChangingConfiguration;
}
void setChangingConfiguration(int changingConfiguration) {
mChangingConfiguration = changingConfiguration;
}
}
具体策略:减速插值器、加速插值器、线性插值器等
//加速插值器
public class AccelerateInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
//......
}
//线性插值器
public class LinearInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
public float getInterpolation(float input) {
return input;
}
//.....
}
//减速插值器
public class DecelerateInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
public DecelerateInterpolator() {
}
public float getInterpolation(float input) {
float result;
if (mFactor == 1.0f) {
result = (float)(1.0f - (1.0f - input) * (1.0f - input));
} else {
result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor));
}
return result;
}
}
Context : 为Animation类
public abstract class Animation implements Cloneable {
//插值器变量
Interpolator mInterpolator;
//这是插值器
public void setInterpolator(Interpolator i) {
mInterpolator = i;
}
//获取插值器
public Interpolator getInterpolator() {
return mInterpolator;
}
//.....
}
Android源码设计模式解析与实战