在日常开发过程中时常需要用到设计模式,但是设计模式有23种,如何将这些设计模式了然于胸并且能在实际开发过程中应用得得心应手呢?和我一起跟着《Android源码设计模式解析与实战》一书边学边应用吧!
设计模式系列文章
- Android 设计模式之单例模式
- Android 设计模式之Builder模式
- Android 设计模式之观察者模式
- Android 设计模式之代理模式
- Android 设计模式之装饰模式
- Android 设计模式之外观模式
- Android 设计模式之原型模式
- Android 设计模式之工厂方法模式
- Android 设计模式之适配器模式
- Android 设计模式之桥接模式
- Android 设计模式之状态模式
- Android 设计模式之面向对象的六大原则
今天我们要讲的是策略模式
定义
策略模式定义了一系列算法,并将每一个算法封装起来,而且使它们可以相互替换。策略模式让算法独立于使用它的客户端而独立变化
使用场景
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时
- 需要安全地封装多种同一类型的操作时
- 出现同一抽象类有多个子类,而又需要if-else或者switch-case来选择具体的子类时
使用例子
- Android中属性动画的时间差值器分为线性差值器、加速减速差值器等,这些差值器里面就用到了策略模式来隔离不同的动画速率计算算法
实现
3大角色
- 用来操作策略的上下文环境
- 策略的抽象
- 具体的策略实现
实现的要点
- 将不同策略的相同的行为抽象到抽象策略中
- 具体的策略实现不同的算法
- 上下文环境根据需要注入需要的策略,并把相应的操作委托给注入的策略处理
实现方式
下面我们以计算不同交通工具的车费来简单看看策略模式的实现
- 首先抽象出计算车费的操作,因为不同的策略最后都会计算车费并返回结果
public interface CalculateStragety {
/**
* 根据公里数计算价格
*
* @param km 公里数
* @return 价格
*/
int calculatePrice(int km);
}
- 然后我们分别实现具体的策略,比如计算公交车的车费的策略
public class BusStragety implements CalculateStragety {
/**
* 十公里之内一元,超过十公里每加一元钱可以坐5公里
* @param km 公里数
* @return 公交车车费
*/
@Override
public int calculatePrice(int km) {
//超过十公里的总距离
int extraTotal = km - 10;
// 超过的距离是5公里的倍数
int extraFactor = extraTotal / 5;
//超过的距离对5公里取余
int fraction = extraTotal % 5;
//价格计算
int price = 1 + extraFactor * 1 ;
return fraction > 0 ? ++price : price;
}
}
- 再加一个出租车的车费计算策略
public class TaxiStragety implements CalculateStragety {
/**
* 出租车车费为每公里2元
* @param km 公里数
* @return 出租车车费
*/
@Override
public int calculatePrice(int km) {
return km * 2;
}
}
- 然后我们看看怎么根据需要注入不同的策略,并把具体的计算委托给注入的策略
public class TrafficCalculator {
public static void main(String[] args) {
TrafficCalculator trafficCalculator = new TrafficCalculator();
trafficCalculator.setCalculateStragety(new BusStragety());
trafficCalculator.calculatePrice(66);
}
CalculateStragety mCalculateStragety;
/**
* 根据需要注入相应的策略
*
* @param calculateStragety 注入的策略
*/
public void setCalculateStragety(CalculateStragety calculateStragety) {
mCalculateStragety = calculateStragety;
}
/**
* 把具体的计算委托给注入的策略
*
* @param km 公里数
* @return 车费
*/
private int calculatePrice(int km) {
return mCalculateStragety.calculatePrice(km);
}
}
- 在上面的例子中我们通过在TrafficCalculator中动态注入计算公交车车费的策略来计算公交车费,当然我们也可以计算出租车费,只需要把注入的策略改为出租车车费计算策略就可以了。
- 以上就是策略模式的简单实现了。
策略模式和代理模式
- 策略模式和代理模式在应用情景上有点相似,都是处理有多种实现方式或是有多种情况需要考虑的情况,而且都是通过抽象提取各个子类的共同行为。但是2种模式还是有很多不同之处。
- 首先代理模式有代理类,而策略模式没有。
- 代理模式把对子类的选择封装在了代理类中,并通过代理类对外提供服务;而策略模式则是通过动态注入的方式来让客户端选择需要的策略
- 策略模式更侧重于策略或是算法的封装隔离;而代理模式更侧重于通过代理类提供代理服务
- 最后,2者都有个缺点,就是随着策略的增加或是要考虑的情况增多,子类也会变得越来越多
总结
- 策略模式主要用来分离算法,在相同的行为抽象下有不同的具体实现策略。
- 策略模式很好地展示了开闭原则,也就是定义抽象,注入不同的实现,从而达到很好的扩展性
- 当我们在实现一个功能时遇到很多if-else或是switch-case的时候就可以考虑下这里是不是可以用策略模式了
源码地址:https://github.com/snowdream1314/DesignPatternsExamples
欢迎关注我的微信公众号,期待与你一起学习,一起交流,一起成长!