实习做的项目,有那么几个功能举要疯狂的使用if-else来进行判断,之前老哥用了工厂模式进行解决。翻看阿里的Java手册发现推荐使用…卫语句,策略模式或状态模式。
卫语句和if-else相比区别不大,无非就是可读性更强了一些,但是维护难度一点没降低,可扩展性一点没提高。一旦需求更改,需要修改所有使用更改需求的if-else代码块。不变还好一变想想都闹心。所以还是看看这个策略模式。
策略模式
0.简介
个人理解,从代码角度来看,策略模式就是OOP封装的体现,他定义一系列的算法,用不同的类把它们一个个封装起来, 共同实现一个接口。
其中需要调用这个算法的地方称之为——环境(Context);
共同实现的接口称之为——抽象策略(Strategy)角色;
每一个具体的实现类称之为——具体策略(ConcreteStrategy)角色。
1.结构
我们按照这个可以简单的写个框架。
环境
public class Context {
// 持有一个具体策略的对象
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
// 策略方法
public void contextMethod() {
strategy.strategyMethod();
}
}
抽象策略角色
/**
* @Description:抽象策略
* @Author: scz
*/
public interface Strategy {
/**
* @Description:规定的策略方法
* @Return: void
* @Author: scz
*/
void strategyMethod();
}
具体策略
/**
* @Description:具体策略方法
* @Author: scz
*/
public class ConcreteStrategyA implements Strategy {
@Override
public void strategyMethod() {
//TODO 具体实现
}
}
2.实例
下班回家,可以坐公交也可以,骑车也可以,有两种策略。
回家的人的名字作为参数进行传递。
首先创建策略接口
package com.inter;
public interface GoHomementStrategy {
/**
* @Description:回家抽象策略接口
* @Date: 17:17 2019-08-06
* @Param: [name]
* @Return: void
* @Author: scz
*/
public void gohome(String name);
}
具体策略实现
坐公交
package com.impl;
import com.inter.GoHomementStrategy;
public class BusGoHomementStrategy implements GoHomementStrategy {
private Integer money;
private String time;
public BusGoHomementStrategy(Integer money, String time) {
this.money = money;
this.time = time;
}
/**
* @Description: 坐公车回家具体策略
* @Date: 17:06 2019-08-06
* @Param: [name] 回家人名字
* @Return: void
* @Author: scz
*/
@Override
public void gohome(String name) {
System.out.println(name+"坐公交回家啦~");
}
}
骑车
package com.impl;
import com.inter.GoHomementStrategy;
public class BicycleGoHomementStrategy implements GoHomementStrategy {
private Integer money;
private String time;
public BicycleGoHomementStrategy(Integer money, String time) {
this.money = money;
this.time = time;
}
/*
* @Description:骑车回家人具体策略
* @Date: 17:06 2019-08-06
* @Param: [name] 回家人名字
* @Return: void
* @Author: scz
*/
@Override
public void gohome(String name) {
System.out.println(name+"骑车回家啦~");
}
}
工作人类,让他自己选怎么回家
package com.text;
import com.inter.GoHomementStrategy;
public class WorkerContext {
private GoHomementStrategy goHomementStrategy;
/**
* 决策使用什么方法回家
* @param name
*/
public void goHome(String name){
goHomementStrategy.gohome(name);
}
public WorkerContext() {
}
public WorkerContext(GoHomementStrategy goHomementStrategy) {
this.goHomementStrategy = goHomementStrategy;
}
public GoHomementStrategy getGoHomementStrategy(){
return goHomementStrategy;
}
public void setGoHomementStrategy(GoHomementStrategy goHomementStrategy) {
this.goHomementStrategy = goHomementStrategy;
}
}
测试下
package com.test;
import com.impl.BicycleGoHomementStrategy;
import com.impl.BusGoHomementStrategy;
import com.text.WorkerContext;
public class GoHomementClient {
public static void main(String[] args) {
// 创建用户
// 创建公交回家策略
WorkerContext workerContext = new WorkerContext();
BusGoHomementStrategy busGoHomementStrategy = new BusGoHomementStrategy (1, "2");
workerContext.setGoHomementStrategy(busGoHomementStrategy);
// 创建骑车回家策略
WorkerContext workerContextBy = new WorkerContext();
BicycleGoHomementStrategy bicycleGoHomementStrategy = new BicycleGoHomementStrategy(1,"2");
workerContextBy.setGoHomementStrategy(bicycleGoHomementStrategy);
// 公交回家啦~
workerContext.goHome("scz");
//骑车回家啦~
workerContextBy.goHome("zcs");
}
}
运行结果:
3.总结
- 完美符合 OCP 原则,可以看到 Context 对象对修改是关闭的,添加新的策略,不需要修改
Context,代码后期维护性以及可扩展性非常高(优点); - 客户端或用户必须知道所有的策略类,并自行决定使用哪一个策略类(缺点);
每增加一个策略,设计中类的数目也会相应增加,这是为了要获得程序的可扩展性及弹性所付出的代价(缺点)。 - 如果你的代码不是一次性的,后期可能会不断加入不同的策略,那么策略模式的设计是绝对值得的。
参考博客:https://blog.csdn.net/championhengyi/article/details/86649264