策略模式+元注解方式替代大量if else写法
1、策略模式简介
设计模式的知识可以参考我的设计模式笔记专栏:设计模式系列博客
策略模式:定义一系列算法,然后将每一个算法封装起来,并将它们可以互相替换。也就是将一系列算法封装到一系列策略类里面。策略模式是一种对象行为型模式。策略模式符合“开闭原则“
Strategy Pattern: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
策略模式包括如下角色:
Context :环境类
Strategy:抽象策略类
ConcreteStrategy:具体策略类
策略模式和状态模式常用于处理业务比较繁杂的场景,因为业务经常变更,有时候随着业务堆积,会出现大量的if...else,造成代码可读性变差,所以可以使用策略模式和状态模式等设计模式进行业务解耦,提高代码可读性
2、典型例子实现
业务场景:提供一个统一的页面,嵌套各个子系统,点击各个子系统时候,会进行业务处理,然后进行跳转
业务听起来很简单,所以就简单敲下代码:
public ModelAndView toSysPage(@RequestParam("type")String type, HttpServletRequest request){
String viewName = "login/unifyLogin";
String isCaLogin = request.getParameter(IS_CA_LOGIN);
if (!StringUtils.isEmpty(isCaLogin) && "true".equalsIgnoreCase(isCaLogin)) {
if (SysTypeEnum.SYS_APPR_CONTROL.getType().equals(type) ) {
viewName = "login/yzsCA";
} else if(SysTypeEnum.SYS_APPR_UNION_CONTROL.getType().equals(type) ) {
viewName = "login/ydblCA";
} else if(SysTypeEnum.SYS_APPR_UNIFY_WEB.getType().equals(type) ) {
viewName = "login/jsgcCA";
}
}
if (SysTypeEnum.SYS_APPR_CONTROL.getType().equals(type) && (StringUtils.isEmpty(isCaLogin) || !"true".equals(isCaLogin))) {
viewName = "login/yzsLogin";
} else if(SysTypeEnum.SYS_APPR_UNION_CONTROL.getType().equals(type) && (StringUtils.isEmpty(isCaLogin) || !"true".equals(isCaLogin))) {
viewName = "login/ydblLogin";
} else if(SysTypeEnum.SYS_APPR_UNIFY_WEB.getType().equals(type) && (StringUtils.isEmpty(isCaLogin) || !"true".equals(isCaLogin))) {
viewName = "login/jsgcLogin";
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName(viewName);
return modelAndView;
}
然后,和现场沟通,发现还要增加系统,业务也要增加,所以就要增加if...else的数量,业务一堆积,代码就变得很杂,不好维护,所以用策略模式进行改进
- 定义元注解:
import org.springframework.stereotype.Service;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited //子类可以继承此注解
public @interface SysType {
String type();
}
- 写个策略接口
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
public interface SysHandler {
ModelAndView invokeModelAndView(Map<String,Object> params);
}
- 各个系统都实现接口,进行不同的业务处理,
@SysType(type = "sys1")表示系统type,@Component记得加上,才可以加到Spring容器里
@SysType(type = "sys1")
@Component
public class ApprControlSysHandler implements SysHandler{
@Override
public ModelAndView invokeModelAndView(Map<String,Object> params) {
//...
return modelAndView;
}
}
- 在一个@Service类里,将实现SysHandler接口的类都装载到Spring容器
public static Map<String, SysHandler> sysHandlerMap = new HashMap<String, SysHandler>(16);
@Autowired
ApplicationContext applicationContext;
/**
* 装载到Spring容器
* @Author nicky
* @Date 2020/06/23 17:47
* @Param [applicationContext]
* @return void
*/
@PostConstruct
public void buildSysHandlerMap() {
Map<String, Object> map = applicationContext
.getBeansWithAnnotation(SysType.class);
for (Map.Entry<String, Object> entry : map.entrySet()) {
Class<SysHandler> sysHandlerClass = (Class<SysHandler>)entry.getValue().getClass() ;
String type = sysHandlerClass.getAnnotation(SysType.class).type();
sysHandlerMap.put(type,applicationContext.getBean(sysHandlerClass));
}
}
- 调用,进行改造,代码简洁很多
public ModelAndView toSysPage(String type, HttpServletRequest request){
Assert.notNull(type, "type can not null");
SysHandler sysHandler = sysHandlerMap.get(type);
Map<String, Object> params = new HashMap<String, Object>(16);
params.put("isCaLogin", isCaLogin);
params = Collections.unmodifiableMap(params);
return modelAndView = sysHandler.invokeModelAndView(params);
}
看了类图,也很清晰,这是策略模式的简单应用,有什么问题欢迎指出

策略模式+元注解方式替代大量if else写法的更多相关文章
- Spring 实现策略模式--自定义注解方式解耦if...else
策略模式 定义 定义一簇算法类,将每个算法分别封装起来,让他们可以互相替换,策略模式可以使算法的变化独立于使用它们的客户端 场景 使用策略模式,可以避免冗长的if-else 或 switch分支判断 ...
- Java/C++实现策略模式---旅游出行方式
旅游的出行方式有乘坐飞机旅行.乘火车旅行和自行车游,不同的旅游方式有不同的实现过程,客户可以根据自己的需要选择一种合适的旅行方式. 类图: Java代码: public class Person { ...
- 如何优雅的用策略模式,取代臃肿的 if-else 嵌套,看这篇就够了
经常听同事抱怨,订单来源又加了一种,代码又要加一层if-else判断,光判断订单来源的if-else就好几百行代码,代码我都不想看了,相信很多同行都有过这样的感受! Java的二十几种设计模式背的滚瓜 ...
- 【策略模式】策略模式结合Spring实战Demo
策略模式 策略模式用于解决判断分支过多的问题,使代码变得简洁和优雅, 策略模式在多种方式在项目中落地,下面举例说明通过指定不同类型的订单使用策略模式执行不同的业务逻辑 文章参考自公众号:石杉的架构笔记 ...
- Java设计模式之策略模式(Strategy)
前言: 最近一直在学习基于okHttp网络请求,学习的过程中就想起了之前项目中有这么一个需求不同的接口要采用不同的加密方式,比如登录之前要采用RSA加密,登录之后要采用AES加密,当时是采用靠传递一个 ...
- Android使用的设计模式2——策略模式
今天讲解一下策略模式,策略模式也是很常用的设计模式,对多种算法或者数据结构选择使用的情况下,经常会使用策略模式来管理这些算法.下面会简单讲解一下策略模式的概念和基本实现.然后结合Android里面的实 ...
- 重构11-Switch to Strategy(Switch到策略模式)
重构没有固定的形式,多年来我使用过不同的版本,并且我敢打赌不同的人也会有不同的版本. 该重构适用于这样的场景:switch语句块很大,并且会随时引入新的判断条件.这时,最好使用策略模式将每个条件封装到 ...
- Android设计模式—策略模式
1.策略模式概念 定义一系列算法,把他们独立封装起来,并且这些算法之间可以相互替换.策略模式主要是管理一堆有共性的算法,客户端可以根据需要,很快切换这些算法,并且保持可扩展性. 策略模式的本质:分离算 ...
- SpringBoot自定义初始化Bean+HashMap优化策略模式实践
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 传统的策略模式一般是创建公共接口.定义公共方法-->然后创建实体类实现公共接口.根据各自的 ...
- 策略模式+注解 干掉业务代码中冗余的if else...
前言: 之前写过一个工作中常见升级模式-策略模式 的文章,里面讲了具体是怎样使用策略模式去抽象现实中的业务代码,今天来拿出实际代码来写个demo,这里做个整理来加深自己对策略模式的理解. 一.业务 ...
随机推荐
- 一款基于 .NET 开源、可以拦截并修改 WinSock 封包的 Windows 软件
前言 今天大姚给大家分享一款基于 .NET 开源(MIT license).可以拦截并修改 WinSock 封包的 Windows 软件:WinsockPacketEditor. 工具介绍 Winso ...
- (Pytorch第三天)复制官网教程程序遇到的一系列报错
先说一下,我之前没学过Python,但是鉴于我是一名c语言高手(雾),我决定现学现用. 首先是https://pytorch.org/tutorials/beginner/basics/optimiz ...
- Git 中的“撤销”
(1)当commit 完后,发现少add几个文件,可以: $ git commit -m 'initial commit' $ git add forgotten_file $ git commit ...
- [RCTF2015]EasySQL 报错注入与二次注入
[RCTF2015]EasySQL 报错注入与二次注入 二次注入,可以概括为以下两步: 第一步:插入恶意数据 进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据 ...
- CF1928G Vlad and Trouble at MIT
CF1928G Vlad and Trouble at MIT Vlad and Trouble at MIT Problem MIT的学生宿舍可以用一棵有\(n\)个顶点的树来表示,每个顶点代表一个 ...
- 校内NOI模拟赛006T1 签到sign 线性基
感想 这道题还算良心,有30pts的暴力--但是这次模拟赛又双叒叕是勒堕赛制,而且试题的标题居然还是NOI模拟测试!打暴力的时候我也没有想到我可以现学现卖一个线性基呢... 数据又是脚造的( 虽然标题 ...
- Java中XML相关
XML的两种解析方式: 1.DOM解析:将标记语言一次性读入内存并在内存中生成一颗DOM树(适用于服务端) 优点:操作方便,可以对文档进行CURD操作 缺点:由于它是一次性全部读入内存的所以占用内存空 ...
- MySQL基础学习——SQL对数据库中表的记录进行操作
SQL对数据库中表的记录进行操作 sql添加表的记录 语法: 向表中插入某些列:insert into 表名 (列名1,列名2,列名3...) values(值1,值2,值3....); 向表中插入所 ...
- K8s新手系列之CronJob
概述 官方文档:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/cron-jobs/ CronJob控制器以 Job控制 ...
- vLLM部署实战重难点
Kubernetes + 容器化部署 vLLM官方docker镜像: vllm/vllm-openai 这是官方提供的 Docker 镜像,可以用来快速部署 vLLM 服务,便于容器化管理. 实战: ...