策略模式:定义了一系列的算法,将每一种算法封装起来并可以相互替换使用,策略模式让算法独立于使用它的客户应用而独立变化。
策略模式中的角色
抽象策略:抽象策略通常由一个接口或抽象类实现,定义公共的策略方法。
具体抽象:具体策略实现具体的策略算法,封装相关的算法和行为。
上下文环境:上下文环境中含有一个对具体策略对象实例的引用,最终供客户端应用程序调用。
类图
应用场景
现在考虑一种情景,一个人每天去上班,他有多种交通方式可以选择,自行车、公交、地铁等等。这时选择不同的交通工具就是选择不同的策略。
代码实现
抽象策略:
package com.huey.pattern.strategy; /** * the abstract strategy * @author huey * @version 1.0 * @created 2015-11-25 */ public interface VehicleStrategy { public String getVehicle(); /** * the algorithm * @param distance, unit: km * @return time, unit: hour */ public double countTime(double distance); }
具体策略 A:
package com.huey.pattern.strategy; /** * the concrete strategy * @author huey * @version 1.0 * @created 2015-11-25 */ public class BusStrategy implements VehicleStrategy { public static final String VEHICLE = "bus"; @Override public String getVehicle() { return VEHICLE; } @Override public double countTime(double distance) { final double speed = 40; // km/h return distance / speed; } }
具体策略 B:
package com.huey.pattern.strategy; /** * the concrete strategy * @author huey * @version 1.0 * @created 2015-11-25 */ public class MetroStrategy implements VehicleStrategy { public static final String VEHICLE = "metro"; @Override public String getVehicle() { return VEHICLE; } @Override public double countTime(double distance) { final double speed = 120; // km/h return distance / speed; } }
上下文环境:
package com.huey.pattern.strategy; /** * the context object in strategy pattern. * @author huey * @version 1.0 * @created 2015-11-25 */ public class Commuter { private String commuterName; public Commuter(String commuterName) { this.commuterName = commuterName; } /** * * @param distance, unit: km */ public void goToWork(double distance, VehicleStrategy vehicleStrategy) { double time = vehicleStrategy.countTime(distance) * 60; // minute String output = String.format("It takes %s %.1f minutes to go to the office by %s everday.", commuterName, time, vehicleStrategy.getVehicle()); System.out.println(output); } }
单元测试:
package com.huey.pattern.strategy; public class StrategyPatternTest { public static void main(String[] args) { Commuter huey = new Commuter("Huey"); huey.goToWork(20, new BusStrategy()); Commuter jane = new Commuter("Jane"); jane.goToWork(30, new MetroStrategy()); } }
结果输出:
It takes Huey 30.0 minutes to go to the office by bus everday. It takes Jane 15.0 minutes to go to the office by metro everday.
策略模式的适用场合
1) 当多个类的表现行为不同,需要在运行时动态选择具体要执行的行为的时候;
2) 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其他方式实现的时候;
3) 需要隐藏具体的策略(算法)的实现细节,各个具体策略(算法)彼此独立的时候;
4) 当一个类中出现了多种行为而且在一个操作中使用多个条件分支来判断使用多种行为的时候,可以使用策略模式将各个条件分支的动作植入具体的策略中实现。