策略模式
策略模式,允许你有多种不同的算法处理某个问题,并且根据你的需求执行特定的算法。
例如,你去商场购物,从家里到商场有3中可选方案
- 出租车
- 步行
- 三轮车
如果你把这三种方案放在一个类里,使用if-else进行判断也不是不可以,只是代码可能会变得臃肿且不方便维护。
我们把每一种方案放在一个类里,对方案的修改也只是在本类中进行调整,而不会说修改步行方案,影响到了出租车方案。
如果后期还有其他出行方案,如滴滴打车,骑电动车等等,只需扩展相应的类和路由即可。
CommuteWay是所有方案的通用接口,描述了到达商场所需要的时间和花费
public interface CommuteWay {
/**
* 花费的时间
* @return
*/
Integer costMinutes();
/**
* 花费的钱(元)
* @return
*/
Integer costMoney();
}
系统目前提供的方案
public enum Ways {
TAX,WALKING,THREE_WHEEL
}
出租车
public class TaxCommute implements CommuteWay{
@Override
public Integer costMinutes() {
return 5;
}
@Override
public Integer costMoney() {
return 8;
}
}
三轮
public class WalkingCommute implements CommuteWay{
@Override
public Integer costMinutes() {
return 20;
}
@Override
public Integer costMoney() {
return 0;
}
}
步行
public class WalkingCommute implements CommuteWay{
@Override
public Integer costMinutes() {
return 20;
}
@Override
public Integer costMoney() {
return 0;
}
}
路由,具体执行哪一种方案
public class RoutingCommuteWay implements CommuteWay {
private CommuteWay commuteWay;
public RoutingCommuteWay(Ways way) {
switch (way) {
case TAX:
commuteWay = new TaxCommute();
break;
case WALKING:
commuteWay = new WalkingCommute();
break;
case THREE_WHEEL:
commuteWay = new ThreeWheelCommute();
break;
default:
throw new RuntimeException("there is no such way");
}
}
@Override
public Integer costMinutes() {
return commuteWay.costMinutes();
}
@Override
public Integer costMoney() {
return commuteWay.costMoney();
}
}
测试
public class AppMain {
private static final Logger LOGGER = LoggerFactory.getLogger(AppMain.class);
public static void main(String[] args) {
// RoutingCommuteWay commuteWay = new RoutingCommuteWay(Ways.TAX);
// RoutingCommuteWay commuteWay = new RoutingCommuteWay(Ways.WALKING);
Ways[] values = Ways.values();
for (Ways strategy : values) {
RoutingCommuteWay commuteWay = new RoutingCommuteWay(strategy);
LOGGER.info("currenty strategy is {}, cost {} minutes,cost {} yuan",strategy.name(),commuteWay.costMinutes(),commuteWay.costMoney());
}
}
}
测试结果
16:26:24.243 [main] INFO com.example.designpattern.strategy.AppMain - currenty strategy is TAX, cost 5 minutes,cost 8 yuan
16:26:24.251 [main] INFO com.example.designpattern.strategy.AppMain - currenty strategy is WALKING, cost 20 minutes,cost 0 yuan
16:26:24.252 [main] INFO com.example.designpattern.strategy.AppMain - currenty strategy is THREE_WHEEL, cost 10 minutes,cost 6 yuan
可以看到,当选取的方案不同时,便会切换到对应的方案,并进行计算花费的时间和金钱。
优点:
易于扩展算法,方便维护代码
参考:Mybatis的RoutingStatementHandler
public class RoutingStatementHandler implements StatementHandler {
private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
return delegate.query(statement, resultHandler);
}
//······省略其他代码
}