23种设计模式之策略模式
来源:互联网 发布:命令行启动mysql 编辑:程序博客网 时间:2024/06/16 12:42
策略模式的定义:
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们还可以相互替换,策略模式让算法独立于使用它的客户端而独立变化。
策略模式的使用场景:
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时
- 需要安全地封装多种同一类型的操作时
- 出现同一抽象类有多个子类,而又需要使用if-else或者 switch-case 来选择具体子类时
类图:
- Context:用来操作策略的上下文环境
- Stragety:策略的抽象
- ConcreteStragegyA,ConcreteStragegyB,ConcreteStragegyC:具体的策略实现
简单实现:
通常如果一个问题有多个解决方案时,比较简单的方式就是利用if-else或者switch-case 方式来根据不同的场景选择不同的解决方案,OK,咱们以北京的公交车为例,参考《Android源码设计模式》,首先看下通常的编写方式
public class PriceCalculator { //公交车类型 private static final int BUS = 1; //地铁类型 private static final int SUBWAY = 2; public static void main(String[] args) { PriceCalculator calculator = new PriceCalculator(); System.out.println("坐16公里的公交车票价位:" + calculator.calculatePrice(16, BUS)); } /** * 北京公交车,十公里之内一元钱,超过十公里之后每加一元钱可以乘5公里 * * @param km * @return */ private int busPrice(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; } /** * 6公里(含)内3元,6~12公里(含)4元,12~22公里(含)5元,22~32公里(含)6元 * * @param km * @return */ private int subwayPrice(int km) { if (km <= 6) { return 3; } else if (km < 12) { return 4; } else if (km < 22) { return 5; } else if (km < 32) { return 6; } return 7; } private int calculatePrice(int km, int type) { if (type == BUS) { return busPrice(km); } else if (type == SUBWAY) { return subwayPrice(km); } return 0; }}
如果想增加一个选择,只能在else-if中添加
private int calculatePrice(int km, int type) { if (type == BUS) { return busPrice(km); } else if (type == SUBWAY) { return subwayPrice(km); }else if(type == TAXT) { return taxiPrice(km); } return 0; }
很明显,PriceCalculator 类不是单一职责,1.计算公交车和地铁乘坐价格的职责。2.还有就是通过if-else的形式来判断使用哪种计算形式。当增加一种出行方式时,就需要增加一个方法。如上代码所示。整体代码比较混乱,这就是我们的主人公—策略模式登场的时候了。我们可以把每一种情景独立成一个函数,然后外部调用方法即可,但是这也是另一种耦合形式,对于可变性较大的算法族来说还是不太适合。
策略模式代码重构如下:
//计算接口public interface CalculateStrategy { /** * 按距离来计算价格 * @param km * @return */ int calculatePrice(int km);}//公交车价格计算策略public class BusStrategy implements CalculateStrategy { @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 SubwayStrategy implements CalculateStrategy { @Override public int calculatePrice(int km) { if (km <= 6) { return 3; } else if (km < 12) { return 4; } else if (km < 22) { return 5; } else if (km < 32) { return 6; } return 7; }}
我们再创建一个扮演角色Context角色的类
//公交出行价格计算器public class TranficCalculator { public static void main(String[] args){ TranficCalculator calculator = new TranficCalculator();// //设置策略模式 calculator.setStrategy(new BusStrategy()); //计算价格 System.out.println("公交车乘16公里的价格:"+calculator.calculatePrice(16)); //设置策略模式 calculator.setStrategy(new TaxiStrategy()); //计算价格 System.out.println("出租车乘16公里的价格:"+calculator.calculatePrice(16)); } CalculateStrategy mStrategy; public void setStrategy(CalculateStrategy mStrategy) { this.mStrategy = mStrategy; } public int calculatePrice(int km){ return mStrategy.calculatePrice(km); }}
这样代码就重构完成了,代码逻辑非常清晰,而且耦合性降低了,可扩展性变强了,现在如果增加一个出租车的方式,
//出租车计算策略public class TaxiStrategy implements CalculateStrategy { @Override public int calculatePrice(int km) { return 2 * km; }}
总结:
策略模式主要是用来分离算法,在相同的行为抽象下有不同的具体实现策略。这个模式很好地展示了开闭原则,也就是定义抽象,注入不同的实现,从而达到很好的可扩展性。
优点:
- 结构清晰明了,使用简单直观
- 耦合度相对而言较低,扩展方便
操作封装也更为彻底,数据更安全
缺点:
- 随着策略模式的增加,子类也会变得繁多
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类
- Strategy和Context之间的通信开销
策略模式就到这里,大家对策略模式是不是又有了新的看法呢?
该文章参考《android源码设计模式解析与实战》这本书。
阅读全文
1 0
- 23种设计模式之策略模式
- 23种设计模式之策略模式
- 23种设计模式之策略模式
- 23种设计模式之策略模式
- 23种设计模式之策略模式
- 23设计模式之策略模式(Strategy)
- 23设计模式之策略模式(Strategy)
- 23中设计模式之策略模式
- java_23种设计模式之策略模式
- Java23种设计模式之策略模式
- 26种设计模式之策略模式
- java23种设计模式之策略模式
- java23种设计模式之策略模式
- 23种设计模式之策略模式(Strategy)
- 23种设计模式之策略模式(Strategy Pattern)
- 23种java设计模式之策略模式
- 23种设计模式C++实例之策略模式
- 简述23种java设计模式之策略模式(strategy)
- 0519
- Error: "***" is not translated in "zh" (Chinese) [MissingTranslation]
- 理解为何需要清除浮动及清除浮动的方法
- CentOS6.2搭建DNS服务
- 多个同名ID/class,点击那个取得当前那个的值和属性值
- 23种设计模式之策略模式
- 数学知识小记
- Redis常用命令
- c++作业六
- sort/map/unordered_map自定义类型如何构造比较函数
- CentOS 系统下安装多个tomcat,占用不同的端口
- Map<String, String> 遍历的四种方法
- python 定时执行函数方法
- vue学习笔记(一)(vue webpack+vue-router+nodeJs npm)