java基础巩固-宇宙第一AiYWM:为了维持生计,策略模式阅读总结(策略模式、if...else...太多怎么办,优化呗)~整起

  • 之前碰到一个需求,就是根据系统不同的下位机分布位置,用户可以通过页面的导出功能导出各个地区不同类型的数据,并以excel表格形式导出。
    在这里插入图片描述
    • 这个后端代码中除了必须的通过POI或者easy Excel等技术处理表格形式、以及必要的IO流导出数据代码以及编码格式等,避免不了的就得进行各个重复性的(当时项目中是以地区名称+设备所在位置+时间为导出表名称)表头信息的判断,然后进行一定的处理,伪代码如下:
      if(nameOfExcel == "A"){
      	//按照A方案或者逻辑进行处理
      }else if(){
      	//按照B方案或者逻辑进行处理
      }else{
      	//按照C方案或者逻辑进行处理
      }
      ...
      
    • 很明显,这样写完,功能呢是能实现,但是有几个问题【违背了面向对象编程的开闭原则以及单一原则】:
      • 如果分支变多,这里的代码就会变得臃肿,难以维护,可读性低(有时过多的 if else 会让我们感到脑壳疼)
      • 如果你需要接入一种新的解析类型,那只能在原有代码上修改
        • 开闭原则(对于扩展是开放的,但是对于修改是封闭的):增加或者删除某个逻辑,都需要修改到原来代码
        • 单一原则(规定一个类应该只有一个发生变化的原因):修改任何类型的分支逻辑代码,都需要改动当前类的代码。
    • 所以,针对咱们这种有多个if…else等条件分支,并且 每个条件分支,可以封装起来替换的【或者switch…case…case…case…几十几百几千个case】,我们就可以使用策略模式来优化
  • 策略模式:
    • 策略模式定义了算法族,分别封装起来【将每一个算法封装到具有共同接口的独立的类中】,让它们之间可以相互替换,此模式让 算法的变化独立于使用算法的的客户,咱们中国最著名的策略模式的使用就是:在目的为把事办好的情况下:对症下药、量体裁衣、具体问题具体分析
    • 咱们用这个策略模式的话首先得搞 一个接口或者抽象类,里面两个方法(一个方法匹配类型,一个可替换的逻辑实现方法)
      public interface DemoByHuFileStrategy{
      	//属于哪种文件解析类型
      	FileTypeResolveEnum gainFileType();
      	
      	//封装的公用算法或者叫具体的解析算法
      	void resolve(Object objectparam);
      }
      
    • 然后再搞出 很多个不同策略的实现类,就可以愉快的玩耍了
      //按照A方案或者逻辑进行处理
      @Component
      public class AFileResolve implements DemoByHuFileStrategy{
          
          @Override
          public FileTypeResolveEnum gainFileType() {
              return FileTypeResolveEnum.File_A_RESOLVE;
          }
      
          @Override
          public void resolve(Object objectparam) {
            logger.info("按照A方案或者逻辑进行处理解析文件,参数:{}",objectparam);
            ...
          }
      }
      
      //按照B方案或者逻辑进行处理
      @Component
      public class BFileResolve implements DemoByHuFileStrategy{
          
          @Override
          public FileTypeResolveEnum gainFileType() {
              return FileTypeResolveEnum.File_B_RESOLVE;
          }
      
          @Override
          public void resolve(Object objectparam) {
            logger.info("按照B方案或者逻辑进行处理解析文件,参数:{}",objectparam);
            ...
          }
      }
      
      //按照C方案或者逻辑进行处理
      @Component
      public class CFileResolve implements DemoByHuFileStrategy{
          
          @Override
          public FileTypeResolveEnum gainFileType() {
              return FileTypeResolveEnum.File_C_RESOLVE;
          }
      
          @Override
          public void resolve(Object objectparam) {
            logger.info("按照C方案或者逻辑进行处理解析文件,参数:{}",objectparam);
            ...
          }
      }
      
    • 玩耍时咱们可以引入比较牛B的Spring,咱们 借助spring的生命周期,使用ApplicationContextAware接口,把对应的策略,初始化到map里面。然后对外提供resolveFile方法即可。
      @Component
      public class StrategyUseService implements ApplicationContextAware{
      
        
          private Map<FileTypeResolveEnum, IFileStrategy> iFileStrategyMap = new ConcurrentHashMap<>();
      
          public void resolveFile(FileTypeResolveEnum fileTypeResolveEnum, Object objectParam) {
              IFileStrategy iFileStrategy = iFileStrategyMap.get(fileTypeResolveEnum);
              if (iFileStrategy != null) {
                  iFileStrategy.resolve(objectParam);
              }
          }
      
          //把不同策略放到map
          @Override
          public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
              Map<String, IFileStrategy> tmepMap = applicationContext.getBeansOfType(IFileStrategy.class);
              tmepMap.values().forEach(strategyService -> iFileStrategyMap.put(strategyService.gainFileType(), strategyService));
          }
      }
      
  • 除了策略模式来实现优化,还有几种优化很多很多if else的方法:
    • 可以使用枚举(enum),JDK 1.5 中引入了新的类型——枚举(enum)
      在这里插入图片描述
    • 使用多态:去除 if else 方法,实际开发中应该分别创建一个接口和多个类分别存储,形成这种对应关系
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      • 之前的 if else 判断就可以改为如下代码:
        在这里插入图片描述
    • 工作流可以帮咱们消除项目中大量的 if else 代码,从而让项目更加好维护和扩展。
      • 工作流就是一系列工作所组成的流程,说白了就是像车间中的流水线一样,所有工人只需做好自己的事情即可
      • 为了更好地开发和维护工作流,我们一般会使用 工作流引擎 技术。可以通过可视化拖拽的方式来绘制流程图、并自动生成业务流程代码,而不用自己写 if else,大幅降低开发成本、非程序员也能用。比较成熟的**工作流引擎有 Activiti【企业开发中使用工作流,还是更推荐 Activiti 等成熟的】、flowable-engine 等等**,还有一个 相对轻量纯净的工作流引擎 CompileFlow
        • 工作流引擎 CompileFlow使用
        • Compile Flow 工作流引擎的原理:
          • 就是将用户编辑好的 XML 视图文件编译为 Java 代码。我们点开编译后的 Java 代码就可以看到全局变量、流程等等。虽然说还是用到了 if else,但是咱们作为开发者不需要关心这些 if else 了,定义好流程、写好每个节点要做的工作即可,相当于又是一个Spring这种帮手帮咱们封装了一点东西,咱们只需要使用人家给咱提供的东西就行
    • 使用 return 去掉多余的 else
      在这里插入图片描述
    • 使用 Map 数组,把相关的判断信息,定义为元素信息可以直接避免 if else 判断
      在这里插入图片描述
    • 使用三元运算符也叫三元表达式或者三目运算符/表达式
      在这里插入图片描述
    • 合并条件表达式:项目中有些逻辑判断是可以通过梳理和归纳,变更为更简单易懂的逻辑判断代码
      在这里插入图片描述
    • 从 JDK 1.8 开始引入 Optional 类,在 JDK 9 时对 Optional 类进行了改进,增加了 ifPresentOrElse() 方法,我们 可以借助ifPresentOrElse方法,来消除 if else 的判断
      在这里插入图片描述
  • 策略模式补充:
    • 策略模式 针对同一个问题提供多种策略的处理方式,这些策略之间可以相互替换,在一定程度上提高了系统的灵活性。策略模式非常符合开闭原则,使用者在不修改现有系统的情况下选择不同的策略,而且便于扩展增加新的策略。Netty 在多处地方使用了策略模式,例如 EventExecutorChooser 提供了不同的策略选择 NioEventLoop,newChooser() 方法会根据线程池的大小是否是 2 的幂次,以此来动态的选择取模运算的方式,从而提高性能。EventExecutorChooser 源码实现如下所示:
      public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {
      
          public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
      
          private DefaultEventExecutorChooserFactory() { }
      
          @SuppressWarnings("unchecked")
          @Override
          public EventExecutorChooser newChooser(EventExecutor[] executors) {
      
              if (isPowerOfTwo(executors.length)) {
                  return new PowerOfTwoEventExecutorChooser(executors);
              } else {
                  return new GenericEventExecutorChooser(executors);
              }
          }
          // 省略其他代码
      }
      

巨人的肩膀:
设计模式之禅
Head First 设计模式
spring揭秘
JavaGuide
“程序员田螺 - 设计模式”
Java中文社区

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值