策略模式结合spring使用最佳实战,老程序员才这么写
共 7566字,需浏览 16分钟
·
2021-04-10 11:59
策略模式结合spring使用
我们在项目中经常会遇到if else 特别多的情况,比如前端传了一个type,不同type 数据处理的流程逻辑也不相同,正常情况我们会怎么做呢?就会像下面一样:
if("aa".equals(type)){
//一顿处理
}else if("bb".equals(type)){
//又是一顿处理
}else if(){
}else if(){
}else if(){
}
当然了,自己写的呢我们自己肯定可以看懂了,无所谓啦但是如果让别人看到肯定是这样了:
但是大家都不想写出这样的代码,这时有人就会说了:"没办法啊,刚开始产品给出的需求没有这么多的逻辑 随着产品的需求的迭代,项目时间紧只能在原有的代码上if else了,我们也是无辜的啊!"
确实这是没法避免的 所以一种就是靠自己的项目经验在开始写的时候就知道后续有可能出现这种情况,第二种就是在逻辑判断多的时候及时重构代码(最苦逼了)
说了这么多接下来就是带着大家怎么解决这种 if else多的问题了 这里我使用的是策略模式
成品代码如下 controller 层
@PostMapping("/action")
public String action(@RequestBody ActionVO actionVO){
//大致就是这个思想 具体的细节 需要 你们自己补充啦 什么日志 异常啥的 自己处理一下 爱你们
ActionHandler actionHandler = actionHandlerFactory.getRoutMap().get(actionVO.getType());
if(actionHandler!=null){
actionHandler.handler(actionVO);
}
return "success";
public class ActionHandlerFactory {
private static Map<Byte, ActionHandler> ROUT_MAP;
@Autowired
private TeacherActionHandler teacherActionHandler;
@Autowired
private UserActionHandler userActionHandler;
@PostConstruct
private void init(){
ROUT_MAP= ImmutableMap.<Byte,ActionHandler>builder()
.put(ActionEnum.USER.getType(),userActionHandler)
.put(ActionEnum.TEACHER.getType(),teacherActionHandler).build();
}
public Map<Byte,ActionHandler> getRoutMap(){
return ROUT_MAP;
}
}
真的没有 if else 了,其实是将真正执行代码的handler放在了map中 这样是不是变得优雅了不少啊!
你想变得更加优雅吗 如果你想变得更加优雅 我带你继续研究像我这次的执行业务逻辑的代码 类的继承结构图如下
RequestHandler
public interface RequestHandler<T> {
public void handler(T t);
public void write(T t);
public void read(T t);
public abstract class ActionHandler implements RequestHandler<ActionVO> {
@Override
public void handler(ActionVO actionVO) {
read(actionVO);
write(actionVO);
insert(actionVO);
}
@Override
public void write(ActionVO actionVO) {
}
@Override
public void read(ActionVO actionVO) {
}
public abstract void insert(ActionVO actionVO);
}
这里使用了一个模板模式 这样的话我们真正的业务逻辑执行类只需要继承这个ActionHandler 重写里面自己想要的方法就可以了
public class UserActionHandler extends ActionHandler{
@Override
public void insert(ActionVO actionVO) {
// 就是写 Ctrl+V
System.out.println("im user");
}
@Override
public void write(ActionVO actionVO) {
super.write(actionVO);
//自己逻辑 就是 Ctrl+C
}
@Override
public void read(ActionVO actionVO) {
super.read(actionVO);
//自己的逻辑 卡卡就是干
}
附带一下这个demo引入的jar
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>
用了上述两种设计模式,这样再一看是不是代码更加的优雅,更加的易读了,而且在以后 改每个模块的业务逻辑的时候只需要改自己的handler就可以,也不会影响到其他的代码。
以上就是我个人的理解哈哈哈
如果有什么写的不对的地方欢迎大家给我留言指正!