java中用策略模式替代if-else的大段逻辑

问题:

java本来是一门以面向对象为主的语言,但很多人嘴上说着java面向对象,然后除了表映射实体之外,其他的还是面向过程的思路。
就比如今天要说的,代码中大段大段的if-else判断,每个if-else代码块中又有很多复杂的逻辑,导致整个代码混乱不堪,让别人看到就感觉看到屎一样的代码一样。

那么,如何优雅的替代这些代码呢,其实有个设计模式(策略模式)就很好的解决了这个问题。

情景举例:

比如说订单处理,订单会有多个type状态,比如说
type=1的时候,就执行普通订单的逻辑;
type=2的时候,就执行满减促销订单的逻辑;
type=3的时候,就执行满返促销订单的逻辑;
等等,可能type会有数十种甚至更多种情况。

然后有些人就会开始if-else了,比如有如下的伪代码:

if(type=1){普通订单...(此处省略100多行处理逻辑)
}else if(type=2){满减促销订单...(此处省略100多行处理逻辑)
}else if(type=3){满返促销订单...(此处省略100多行处理逻辑)
}else if(type=n){...(此处省略几百上千行的逻辑)
}

做的好点的,会把if-else代码块中的逻辑,抽成一个个的方法,会稍微显的代码清晰许多,但这些都是面向过程的思想。
我认为,这种情况就应该用以下这种方式,即,用策略模式代替if-else,真正做到面向对象。
把每种不同类型的订单抽成一个个对象,然后通过不同的注解标识来区分调用。

用策略模式代替if-else:

首先,本次例子用的是Spring-Boot框架,亲测没问题。SpringMVC框架应该也是没问题的。
定义一个订单类,里面有type属性,type可以是"1"、“2”、“3”…
定义一个抽象类AbstractHandler,里面有个抽象方法handle,入参是订单类
定义一个注解HandlerType,有个value属性,value是几就代表这个注解注的这个类是什么类型的订单
定义普通类HandlerImpl01,实现AbstractHandler,代表普通订单,即@HandlerType(“1”);
定义普通类HandlerImpl02,实现AbstractHandler,代表满减促销订单,即@HandlerType(“2”);
定义普通类HandlerImpl03,实现AbstractHandler,代表满返促销订单,即@HandlerType(“3”);
定义一个初始化类HandlerProcessor,实现BeanFactoryPostProcessor,过程如下:
1、找到带有注解@HandlerType的类,
2、以注解的值为key,对应的类为value,存在一个map中
3、将这个map作为构造函数的参数,初始化HandlerContext,将HandlerContext注册到spring中成为一个单例bean。
很明显,目的就是为了保存不同type对应的不同类。
定义类HandlerContext,有个map类型的属性叫handlerMap,有个getInstance的方法,入参是type,返回AbstractHandler。
最后使用的时候,是先调用handlerContext.getInstance方法,根据type获取对应的AbstractHandler。
然后再调用他的handle方法,执行对应订单类型的处理逻辑。

具体代码如下:

//@Data是lombok的注解,为了省略不写get/set方法
@Data
public class OrderDTO {private String code;private BigDecimal price;/*** 订单类型* 1:普通订单* 2:满减订单* 3:满返订单*/private String type;
}
public abstract class AbstractHandler {abstract public String handle(OrderDTO orderDTO);
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface HandlerType {String value();
}
@Component
@HandlerType("1")
public class HandlerImpl01 extends AbstractHandler {@Overridepublic String handle(OrderDTO orderDTO) {System.out.println("处理type为1的订单,orderDTO.type="+orderDTO.getType());return "success";}
}
@Component
@HandlerType("2")
public class HandlerImpl02 extends AbstractHandler {@Overridepublic String handle(OrderDTO orderDTO) {System.out.println("处理type为2的订单,orderDTO.type="+orderDTO.getType());return "success";}
}
@Component
@HandlerType("3")
public class HandlerImpl03 extends AbstractHandler {@Overridepublic String handle(OrderDTO orderDTO) {System.out.println("处理type为3的订单,orderDTO.type="+orderDTO.getType());return "success";}
}
@Component
@SuppressWarnings("unchecked")
public class HandlerProcessor implements BeanFactoryPostProcessor {//这里是具体的handler策略类的包的位置,为了后面的包扫描private static final String HANDLER_PACKAGE = "com.zs.handler";@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {Map<String, Class> handlerMap = new HashMap<>();//包扫描ClassScaner.scan(HANDLER_PACKAGE,HandlerType.class).forEach(clazz ->{Annotation annotation = clazz.getAnnotation(HandlerType.class);HandlerType handlerType = (HandlerType) annotation;String type = handlerType.value();System.out.println(type);handlerMap.put(type,clazz);});HandlerContext handlerContext = new HandlerContext(handlerMap);//注册单例beanFactory.registerSingleton(HandlerContext.class.getName(),handlerContext);}
}
public class HandlerContext {private Map<String,Class> handlerMap;public HandlerContext(Map<String, Class> handlerMap) {this.handlerMap = handlerMap;}public AbstractHandler getInstance(String type){Class clazz = handlerMap.get(type);if(clazz == null){throw new IllegalArgumentException("没有type对应的处理器,type:"+type);}return (AbstractHandler)SpringContextUtils.getBean(clazz);}
}

定义接口:

public interface OrderService {/*** 根据订单类型处理订单* @param orderDTO* @return*/String handle(OrderDTO orderDTO);
}

实现接口:

@Service
public class OrderServiceImpl implements OrderService {@Resourceprivate HandlerContext handlerContext;@Overridepublic String handle(OrderDTO orderDTO) {System.out.println("OrderServiceImpl handle 方法开始执行===");AbstractHandler handler = handlerContext.getInstance(orderDTO.getType());return handler.handle(orderDTO);}
}

包扫描的工具类:

public class ClassScaner implements ResourceLoaderAware {private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();private final List<TypeFilter> includeFilters = new LinkedList<TypeFilter>();private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>();private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);public ClassScaner() {}public void setResourceLoader(ResourceLoader resourceLoader) {this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);this.metadataReaderFactory = new CachingMetadataReaderFactory( resourceLoader);}//    public final ResourceLoader getResourceLoader() {//        return this.resourcePatternResolver;
//    }public void addIncludeFilter(TypeFilter includeFilter) {this.includeFilters.add(includeFilter);}//    public void addExcludeFilter(TypeFilter excludeFilter) {//        this.excludeFilters.add(0, excludeFilter);
//    }//    public void resetFilters(boolean useDefaultFilters) {//        this.includeFilters.clear();
//        this.excludeFilters.clear();
//    }public static Set<Class> scan(String basePackage, Class<? extends Annotation>... annotations) {ClassScaner cs = new ClassScaner();for (Class anno : annotations)cs.addIncludeFilter(new AnnotationTypeFilter(anno));return cs.doScan(basePackage);}//    public static Set<Class> scan(String[] basePackages, Class<? extends Annotation>... annotations) {//        ClassScaner cs = new ClassScaner();
//        for (Class anno : annotations)
//            cs.addIncludeFilter(new AnnotationTypeFilter(anno));
//        Set<Class> classes = new HashSet<Class>();
//        for (String s : basePackages)
//            classes.addAll(cs.doScan(s));
//        return classes;
//    }public Set<Class> doScan(String basePackage) {Set<Class> classes = new HashSet<Class>();try {String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX+ org.springframework.util.ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage))+ "/**/*.class";Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);for (int i = 0; i < resources.length; i++) {Resource resource = resources[i];if (resource.isReadable()) {MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);if ((includeFilters.size() == 0 && excludeFilters.size() == 0)|| matches(metadataReader)) {try {classes.add(Class.forName(metadataReader.getClassMetadata().getClassName()));} catch (ClassNotFoundException e) {e.printStackTrace();}}}}} catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return classes;}protected boolean matches(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, this.metadataReaderFactory)) {return false;}}for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, this.metadataReaderFactory)) {return true;}}return false;}
}

spring工具类,为了获取bean

@Component
public class SpringContextUtils implements ApplicationContextAware {private static ApplicationContext applicationContext = null;public static ApplicationContext getApplicationContext(){return applicationContext;}@SuppressWarnings("unchecked")public static <T> T getBean(String beanId) {return (T) applicationContext.getBean(beanId);}public static <T> T getBean(Class<T> requiredType) {return (T) applicationContext.getBean(requiredType);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {SpringContextUtils.applicationContext = applicationContext;}
}

[设计模式] ------ 策略模式实战:java中替代if-else的大段逻辑相关推荐

  1. 设计模式-策略模式(Strategy)-Java

    设计模式-策略模式(Strategy)-Java 目录 文章目录 1.前言 2.示例案例-电影票打折方案 3.策略模式概述 3.1.策略模式定义 3.2.策略模式结构 3.3.策略模式结构图中角色 3 ...

  2. 王者荣耀java实现_从王者荣耀看设计模式-策略模式(java版)

    王者荣耀 曾经我也是一名玩农药的大学生,但现在已经弃了,别问我为什么(被坑爹队友坑的哭...).而今天我们来把让农药变荣耀,我们来从王者荣耀中看设计模式的策略模式. 射手 00.分析 我们先来思考,王 ...

  3. [设计模式] ------ 策略模式

    策略模式 它定义了算法家族,分别封装起来,让他们直接可以互相替换,此模式让算法的变化,不会影响到使用算法的客户 其实很简单,可能很多人都用到了,只不过还不知道这就是策略模式而已. 比如定义一个接口A, ...

  4. Java设计模式-策略模式作业

    Java设计模式-策略模式作业,所有类和接口均在一个package内 文章目录 前言 一.作业内容 二.具体实现 1.类图 2.Strategy接口 3.PreCopyStrategy类 4.Post ...

  5. 设计模式之策略模式(Java 实现)

    设计模式之策略模式(Java 实现) 大家一定都使用过电子地图.在地图中输入出发地和目的地,然后再选取你的出行方式,就可以计算出最优线路以及预估的时长.出行方式有驾车.公交.步行.骑行等.出行方式不同 ...

  6. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...

    23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...

  7. java 策略模式 促销_java设计模式——策略模式

    一. 定义与类型 定义:针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换.策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能.当代码中 ...

  8. 设计模式-工厂模式的3中不同实现[JAVA]

    设计模式-工厂模式的3中不同实现[JAVA] 工厂模式简介 In Factory pattern, we create object without exposing the creation log ...

  9. 设计模式(三)策略模式——在Spring中使用策略模式

    前言 在 设计模式(一)策略模式 -- 策略模式结构 和 设计模式(二)策略模式 -- 在程序中通过枚举使用策略模式 两篇博文中分析了策略模式的基础使用,在实际的项目开发中要结合spring容器使用策 ...

最新文章

  1. 吐血推荐:win下如何安装tensorflow?只需两步!!
  2. sscanf用法总结
  3. R语言seq函数生成数据序列实战
  4. jdk历史各个版本下载
  5. SharePoint 账号
  6. 程序的加载和执行(六)——《x86汇编语言:从实模式到保护模式》读书笔记26
  7. 朋友圈广告助手_腾讯社交广告代理附近推跟朋友圈广告对比优势
  8. 前端学习(2050)vue之电商管理系统电商系统之实现node创建服务器
  9. 我的Go+语言初体验——(1)超详细安装教程
  10. 白盒测试 | 用例设计方法之判定覆盖
  11. MySQL增删改查基础知识
  12. DiagnosticsTextBox:WinForms的日志窗口
  13. Python 函数(三)
  14. html轮播图向左改为向下,jQuery之轮播图向左滚动动画【原创】
  15. JDBC高级特性(一)结果集,批量更新
  16. 【转】所需即所获:像 IDE 一样使用 vim
  17. 物联网消息服务器,GitHub - tian-yuan/CMQ: go 实现的分布式开源物联网MQTT消息服务器...
  18. 优麒麟系统安装MySQL_优麒麟Linux(Ubuntu Kylin)简易安装手册
  19. 航顺HK32F030MF4P6开发脱坑小记
  20. 快速把PDF文档里的表格粘贴到excel的方法

热门文章

  1. 浅谈多重背包及其优化
  2. JavaScript之正方教务系统自动化教评[插件-转载]
  3. Android开发艺术探究Note
  4. 2015毕业找工作纪实|一年的蜕变毕业生
  5. BEGINNING SHAREPOINT#174; 2013 DEVELOPMENT 第3章节--SharePoint 2013 开发者工具 站点设置
  6. 图解 CSS (1): 先做一个样式表测试工具
  7. 2.2.1.处理机调度的概念,层次
  8. 【剑指offer】面试题18:删除链表的节点(Java)
  9. Leetcode--136. 只出现一次的数字
  10. 如何用python做计算软件_如何用Python写一个计算器软件 附带效果图