设计模式的知识能够参考个人设计模式笔记专栏:设计模式系列博客html
策略模式:定义一系列算法,而后将每个算法封装起来,并将它们能够互相替换。也就是将一系列算法封装到一系列策略类里面。策略模式是一种对象行为型模式。策略模式符合“开闭原则“java
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.web
策略模式包括以下角色:算法
Context :环境类spring
Strategy:抽象策略类设计模式
ConcreteStrategy:具体策略类app
策略模式和状态模式经常使用于处理业务比较繁杂的场景,由于业务常常变动,有时候随着业务堆积,会出现大量的if...else,形成代码可读性变差,因此可使用策略模式和状态模式等设计模式进行业务解耦,提升代码可读性ide
业务场景:提供一个统一的页面,嵌套各个子系统,点击各个子系统时候,会进行业务处理,而后进行跳转ui
业务听起来很简单,因此就简单敲下代码:.net
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; } }
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); }
看了类图,也很清晰,这是策略模式的简单应用,有什么问题欢迎指出