策略模式+元注解方式替代大量if else写法

举报
yd_273762914 发表于 2020/12/02 22:41:22 2020/12/02
【摘要】 1、策略模式简介 设计模式的知识可以参考我的设计模式笔记专栏:设计模式系列博客 策略模式:定义一系列算法,然后将每一个算法封装起来,并将它们可以互相替换。也就是将一系列算法封装到一系列策略类里面。策略模式是一种对象行为型模式。策略模式符合“开闭原则“ Strategy Pattern: Define a family of algorithms, encap...

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; }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

然后,和现场沟通,发现还要增加系统,业务也要增加,所以就要增加if…else的数量,业务一堆积,代码就变得很杂,不好维护,所以用策略模式进行改进

  • 定义元注解:

import org.springframework.stereotype.Service;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited  //子类可以继承此注解
public @interface SysType { String type();
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 写个策略接口
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;

public interface SysHandler { ModelAndView invokeModelAndView(Map<String,Object> params);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 各个系统都实现接口,进行不同的业务处理,@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; }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 可以新建一个工厂类或者代理类,将实现SysHandler接口的类都装载到sysHandlerMap里,sysHandlerMap可以做成单例
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)); } }


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 调用,进行改造,代码简洁很多
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); }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

看了类图,也很清晰,这是策略模式的简单应用,有什么问题欢迎指出
在这里插入图片描述

文章来源: smilenicky.blog.csdn.net,作者:smileNicky,版权归原作者所有,如需转载,请联系作者。

原文链接:smilenicky.blog.csdn.net/article/details/107003472

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。