>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 21941 个阅读者 刷新本主题
 * 贴子主题:  项目中的if else太多了,该怎么重构? 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-01-12 15:31:06     消息  查看  搜索  好友  邮件  复制  引用

          

项目中的if else太多了,该怎么重构?

                                                                                                                                               点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

  > >介绍

最近跟着公司的大佬开发了一款IM系统,类似QQ和微信哈,就是聊天软件。我们有一部分业务逻辑是这样的    

  if  (msgType  =  "文本" )  {
// dosomething
}  else  if (msgType  =  "图片" )  {
// doshomething
}  else  if (msgType  =  "视频" )  {
// doshomething
}  else  {
// doshomething
}

就是根据消息的不同类型有不同的处理策略,每种消息的处理策略代码都很长,如果都放在这种if else代码快中,代码很难维护也很丑,所以我们一开始就用了策略模式来处理这种情况。

     策略模式还挺简单的,就是定义一个接口,然后有多个实现类,每种实现类封装了一种行为。然后根据条件的不同选择不同的实现类。

  > >实现过程

消息对象,当然真实的对象没有这么简单,省略了很多属性    

  @Data
@AllArgsConstructor
public  class  MessageInfo  {

     // 消息类型
     private Integer type ;
     // 消息内容
     private String content ;

}

定义一个消息处理接口    

  public  interface  MessageService  {

     void  handleMessage (MessageInfo messageInfo ) ;
}

有2个消息处理接口,分别处理不同的消息

     处理文本消息    

  @Service
@MsgTypeHandler (value  = MSG_TYPE .TEXT )
public  class  TextMessageService  implements  MessageService  {

     @Override
     public  void  handleMessage (MessageInfo messageInfo )  {
        System .out . println ( "处理文本消息 "  + messageInfo . getContent ( ) ) ;
     }
}

处理图片消息    

  @Service
@MsgTypeHandler (value  = MSG_TYPE .IMAGE )
public  class  ImageMessageService  implements  MessageService  {

     @Override
     public  void  handleMessage (MessageInfo messageInfo )  {
        System .out . println ( "处理图片消息 "  + messageInfo . getContent ( ) ) ;
     }
}

文章写到这,可能大多数人可能会想到要需要如下一个Map, Map<消息类型,消息处理对象>,这样直接根据消息类型就能拿到消息处理对象,调用消息处理对象的方法即可。我们就是这样做的,但是我们不想手动维护这个Map对象,因为每次增加新的消息处理类,Map的初始化过程就得修改

     我们使用了注解+ApplicationListener来保存这种映射关系,来看看怎么做的把

     定义一个消息类型的枚举类    

  public  enum MSG_TYPE  {

     TEXT ( 1 ,  "文本" ) ,
     IMAGE ( 2 ,  "图片" ) ,
     VIDEO ( 3 ,  "视频" ) ;

     public  final  int code ;
     public  final String name ;

     MSG_TYPE ( int code , String name )  {
         this .code  = code ;
         this .name  = name ;
     }
}

定义一个注解    

  @Documented
@Inherited
@Target (ElementType .TYPE )
@Retention (RetentionPolicy .RUNTIME )
public @ interface  MsgTypeHandler  {

    MSG_TYPE  value ( ) ;
}

不知道你注意到了没,前面的代码中,每种消息处理类上面都有一个@MsgTypeHandler注解,表明了这个处理类

处理哪种类型的消息    

  @Service
@MsgTypeHandler (value  = MSG_TYPE .TEXT )
public  class  TextMessageService  implements  MessageService  {

     @Override
     public  void  handleMessage (MessageInfo messageInfo )  {
        System .out . println ( "处理文本消息 "  + messageInfo . getContent ( ) ) ;
     }
}

用一个context对象保存了消息类型->消息处理对象的映射关系    

  @Component
public  class  MessageServiceContext  {

     private  final Map  <Integer , MessageService > handlerMap  =  new  HashMap < > ( ) ;

     public MessageService  getMessageService (Integer type )  {
         return handlerMap . get (type ) ;
     }

     public  void  putMessageService (Integer code , MessageService messageService )  {
        handlerMap . put (code , messageService ) ;
     }

}

最精彩的部分到了    

  @Component
public  class  MessageServiceListener  implements  ApplicationListener  <ContextRefreshedEvent >  {

     @Override
     public  void  onApplicationEvent (ContextRefreshedEvent event )  {
        Map  <String , Object > beans  = event . getApplicationContext ( ) . getBeansWithAnnotation (MsgTypeHandler . class ) ;
        MessageServiceContext messageServiceContext  = event . getApplicationContext ( ) . getBean (MessageServiceContext . class ) ;
        beans . forEach ( (name , bean )  - >  {
            MsgTypeHandler typeHandler  = bean . getClass ( ) . getAnnotation (MsgTypeHandler . class ) ;
            messageServiceContext . putMessageService (typeHandler . value ( ) .code ,  (MessageService ) bean ) ;
         } ) ;
     }
}

在spring的启动过程中,通过解析注解,将消息类型->消息处理对象的映射关系保存到MessageServiceContext对象中    

  @Autowired
MessageServiceContext messageServiceContext ;

@Test
public  void  contextLoads ( )  {
// 构建一个文本消息
MessageInfo messageInfo  =  new  MessageInfo (MSG_TYPE .TEXT .code ,  "消息内容" ) ;
MessageService messageService  = messageServiceContext . getMessageService (messageInfo . getType ( ) ) ;
// 处理文本消息 消息内容
// 可以看到文本消息被文本处理类所处理
messageService . handleMessage (messageInfo ) ;
}

测试类正常工作,通过策略模式避免了写大量的if else代码,也更容易维护

                                                                                                                
----------------------------
原文链接:https://blog.csdn.net/zzti_erlie/article/details/102988486

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 sunshine 在 2020-01-13 11:52:10 重新编辑]
  Java面向对象编程-->面向对象开发方法概述之开发思想(上)
  JavaWeb开发-->JSP中使用JavaBean(Ⅱ)
  JSP与Hibernate开发-->第一个helloapp应用
  Java网络编程-->用Spring整合CXF发布Web服务
  精通Spring-->CSS过渡和动画
  Vue3开发-->Vue Router路由管理器
  为网站代码块pre标签增加一个复制代码按钮代码
  用VisualVM远程监控Java进程
  用注解去代替if-else的技巧
  超详细的Java运算符修炼手册(优秀程序员不得不知道的运算技...
  面试必考-static、final和单例模式
  好消息:《Java网络编程核心技术详解》出版
  Java读取大文件的高效率实现_java大文件
  Eclipse使用指南:快速修复功能
  Eclipse使用指南:常用视图(View) 的用法
  Java设计模式:备忘录模式
  Java入门实用代码:获取所有线程
  Java入门实用代码:集合转数组
  Java 入门实用代码:汉诺塔算法
  JAVA日期加减运算
  中国有多少程序员?现在还值得学java吗?
  更多...
 IPIP: 已设置保密
楼主      
1页 1条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。