这是我参与更文挑战的第7天,活动详情查看: 更文挑战
定义
笼统的来说策略模式是定义了一系列算法,并将每一个算法封装起来,而且使它们之间可以相互替换,策略模式让算法独立于使用它的客户而独立变化
使用场景
- 针对同一类型的多种处理方式,仅仅是具体行为有差别的
- 需要安全的分装多种同一类型的操作时
- 出现同一抽象类有多个子嘞,而又需要使用if-else或者switch-case来选择具体子类时候
直白点讲就是大量的if-else 或者 switch-case的情况下,并且他们都有很多共同点,这个时候就可以考虑使用策略模式,把它们封装起来,根据不同的策略选择不同的操作
代码实现
我们先看一段代码,有关出行的;
public class PriceCalculator {
private static final int BUS = 1; //公交车类型
private static final int SUBWAY = 2;//地铁类型
//公交车价格计算
private static int busPrice(int km) {
int extraTotal = km - 10; //超过10公里总距离
int extraFactor = extraTotal / 5; //超过的距离是5公里的倍数
int fraction = extraTotal % 5; //超过的公里对5公里取余数
int price = 1 + extraFactor * 1;//价格计算
return (fraction > 0) ? ++price : price;
}
//地铁价格计算
public static int subwayPrice(int km) {
if (km <= 6) {
return 3;
} else if (km > 6 && km < 12) {
return 4;
} else if (km > 12 && km < 22) {
return 5;
} else if (km > 22 && km < 32) {
return 6;
} else {
return 7;
}
}
//计算价格
public static int calculatePrice(int km, int type) {
if (type == BUS) {
return busPrice(km);
} else if (km == SUBWAY) {
return subwayPrice(km);
}
return 0;
}
public static void main(String[] args) {
PriceCalculator priceCalculator = new PriceCalculator();
System.out.println("坐19公里的公交车票价格为:" + priceCalculator.busPrice(19));
System.out.println("坐19公里的地铁票价格为:" + priceCalculator.subwayPrice(19));
}
}
复制代码
看上面的代码,如果我们想计算出租车出行的价格,或者飞机,火车,动车等等.是不是需要改类,然后写各种if-else判断呢? 这个时候PriceCalculator 很明显就不是单一职责了.它既要计算交通工具乘坐价格,还要if-else判断是哪一种出行攻击.
然后我们用策略模式优化下上边的代码:
新建一个策略的抽象,用来定义计算价格的接口:
//定义一个计算价格的抽象策略接口
public interface CalculateStrategy {
/**
* 按照距离计算价格
* @param km 公里
* @return 返回价格
*/
int calculatePrice(int km);
}
复制代码
然后定义具体的实现策略:Bus/Subway/Taxi 等等
public class BusStrategy implements CalculateStrategy {
@Override
public int calculatePrice(int km) { //北京公交车 10公里之内1元,超过10公里之后每增加1元可以乘坐5公里
int extraTotal = km - 10; //超过10公里总距离
int extraFactor = extraTotal / 5; //超过的距离是5公里的倍数
int fraction = extraTotal % 5; //超过的公里对5公里取余数
int price = 1 + extraFactor * 1;//价格计算
return (fraction > 0) ? ++price : price;
}
}
复制代码
//地铁出行策略类
public class SubwayStrategy implements CalculateStrategy {
@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 if (km > 22 && km < 32) {
return 6;
} else {
return 7;
}
}
}
复制代码
//TAXI 计算策略类
public class TaxiStrategy implements CalculateStrategy {
@Override
public int calculatePrice(int km) {
return km * 2;
}
}
复制代码
然后定义个操作策略的类:
//操作策略的上下文环境
public class TranficCalculator {
public static void main(String[] args) {
TranficCalculator tranficCalculator = new TranficCalculator();
tranficCalculator.setCalculateStrategy(new BusStrategy());
System.out.println("公交车19公里的价格:" + tranficCalculator.calculatePrice(19));
tranficCalculator.setCalculateStrategy(new TaxiStrategy());
System.out.println("Taxi19公里的价格:" + tranficCalculator.calculatePrice(19));
}
private CalculateStrategy calculateStrategy;
public void setCalculateStrategy(CalculateStrategy calculateStrategy) {
this.calculateStrategy = calculateStrategy;
}
public int calculatePrice(int km) {
return calculateStrategy.calculatePrice(km);
}
}
复制代码
是不是清晰明了,需要计算新的出行方式价格,之需要定义新的具体策略类,然后计算, 在操作对象中传递获取就好了.
总结
通过建立抽象接口,将不同的策略构建成一个个具体的策略实现,通过不同的策略实现算法替换,在简化逻辑,结构的同时,增强了代码的可读性,系统的稳定性,可扩展性.后期接手开发的人员能直观的看懂逻辑代码,维护也超级方便
优点
- 结构清晰明了,使用简单直观.
- 耦合度相对之前的代码来说较低,扩展方便,可以快速扩展.
- 操作封装更为彻底,数据更加安全,类职责单一.
缺点
- 随着策略的增加,子类也变得多,增加类的代码量.
后话
RecyclerView 提供了一个新的组件 ConcatAdapter,内部是通过策略模式来区分不同的ViewType ,然后加载不同的Item,感兴趣的话可以了解了解. 后续会出分析文章.
以上就是策略模式模式的全部内容啦, 如果觉得写得不错,不妨点个赞.
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END