前两篇文章分别介绍了Builder模式和Observer模式,本文将介绍另一种Android里面经常用到的设计模式,策略模式。
策略模式是一种通俗易懂的设计模式,常用于组织一些可替换的算法组件,这些算法组件本质上完成同一个性质的任务,可以互相替换,只是实现细节上存在些许差异。
举个例子,为了完成射击敌人的任务,我们可以采取不同的武器进行,手枪,步枪,或者火炮。这里不同的武器就是不同的策略,这些策略可以互相替换,并且都可以实现射击敌人的任务,区别在于执行过程的差异。
利用策略模式,我们可以采用如下的代码实现。
首先抽象出不同射击策略共同的接口:
ShootInterface.java
public interface ShootInterface {
void shoot();
}
该接口包含了射击接口,不同武器实现不同的射击函数。
手枪射击:
PistolStrategy.java
public class PistolStrategy implements ShootInterface{
@Override
public void shoot() {
System.out.println("Pistol shooting, kills 1 enemy every 10 shots.");
}
}
步枪射击:
RifleStrategy.java
public class RifleStrategy implements ShootInterface{
@Override
public void shoot() {
System.out.println("Rifle shooting, one shot, one kill.");
}
}
火炮射击:
CannonStrategy.java
public class CannonStrategy implements ShootInterface {
@Override
public void shoot() {
System.out.println("Cannon shooting, one shot, kills a lot.");
}
}
新建一个消灭敌人的任务类:
EliminateEneryTask.java
public class EliminateEneryTask {
private ShootInterface shootStrategy;
public void setShootStrategy(ShootInterface strategy) {
shootStrategy = strategy;
}
public void action() {
shootStrategy.shoot();
}
}
这个类的setShootStrategy函数用于外部调用来设置具体的设计策略,action方法实施该策略下的射击动作。
调用如下:
public class StrategyPatternDemo {
public static void main(String[] args) {
PistolStrategy pistol = new PistolStrategy();
RifleStrategy rifle = new RifleStrategy();
CannonStrategy cannon = new CannonStrategy();
EliminateEneryTask task = new EliminateEneryTask();
task.setShootStrategy(pistol);
task.action();
task.setShootStrategy(rifle);
task.action();
task.setShootStrategy(cannon);
task.action();
}
}
这种模式下,我们新添加一种射击策略也很简单,只需要新加一个实现了ShootInterface接口的类,并实现shoot方法即可,无需修改EliminateEneryTask类。同样的需求如果不使用策略模式,我们可能需要在EliminateEneryTask里面设置一系列的if/else进行策略的判断,显然不如这种方式优雅。
在Android属性动画中,ValueAnimator类的插值器(Interpolator)就使用了策略模式:
ValueAnimator animator = ValueAnimator.ofInt(0,600);
animator.setDuration(1000);
animator.setInterpolator(new LinearInterpolator());
animator.start();
通过ValueAnimator的setInterpolator函数,可以设置不同的插值器,也就是不同的插值策略,比如线性插值器LinearInterpolator,加速度插值器AccelerateInterpolator,减速度插值器DecelerateInterpolator等。它们都实现了TimeInterpolator接口,完成各自的插值计算,并提供统一的对外调用函数:
public interface TimeInterpolator {
float getInterpolation(float input);
}
这样就可以通过setInterpolator设置任意的插值策略,包括自己实现的策略。
像策略这种设计模式,本身并没有什么高深的地方,只要了解过一次,就能简单的套用在日常编程中,运用得当的话,能显著提高代码质量,是一种低成本,高收益的设计模式。
网友评论