用枚举干掉switch

原代码

消息类型的枚举:

public enum WxocTemplateMessageTypeEnum {

    /**
     * 电话访谈活动开始之前
     */
    BEFORE_TELEPHONE_INTERVIEW_ACTIVITY_START,


    /**
     * 路演活动开始之前
     */
    BEFORE_ROAD_SHOW_ACTIVITY_START,

    /**
     * 会议结束通知
     */
    ACTIVITY_END,

    /**
     * 会议取消通知
     */
    ACTIVITY_CANCEL,

    ;

}

消息控制器发送消息的方法


 private void sendWxoxTemplateMessage(MessageTypeEnum type,ISystemMessageConsumerService messageConsumer,String body){
        log.debug("消息消费-发送公众号模版消息处理开始");
        if(type.isSendWxoxTemplateMessage()){
            //获取消息模版类型
            WxocTemplateMessageTypeEnum templateMessageTypeEnum = messageConsumer.getWxocTemplateMessageTypeEnum(body);
            if(templateMessageTypeEnum==null){
                log.debug("消息消费-发送公众号模版消息-未知的消息类型");
                return ;
            }
            WxocTemplateMessageForm templateMessageForm = messageConsumer.generateWxocTemplateMessageForm(body);
            if(templateMessageForm==null){
                log.debug("消息消费-发送公众号模版消息-生成消息模版失败");
                return ;
            }
            Integer wxocUserId = messageConsumer.getWxocUserId(body);
            if(wxocUserId==null){
                log.debug("消息消费-发送公众号模版消息-没有有效的微信公众号用户");
                return ;
            }
            
            switch (templateMessageTypeEnum){
                case BEFORE_TELEPHONE_INTERVIEW_ACTIVITY_START:
                    innerProjectWxocApi.sendBeforeTelephoneInterviewTemplateMessage(wxocUserId,templateMessageForm);
                    break;
                case BEFORE_ROAD_SHOW_ACTIVITY_START:
                    innerProjectWxocApi.sendBeforeRoadShowActivityStartTemplateMessage(wxocUserId,templateMessageForm);
                    break;
                case ACTIVITY_CANCEL:
                    innerProjectWxocApi.sendActivityCancelTemplateMessage(wxocUserId,templateMessageForm);
                    break;
                case ACTIVITY_END:
                    innerProjectWxocApi.sendActivityEndTemplateMessage(wxocUserId,templateMessageForm);
                    break;
                case RECEIPT_OF_ACCOUNT:
                    innerProjectWxocApi.sendReceiptOfAccountTemplateMessage(wxocUserId,templateMessageForm);
                    break;
                
                default:
            }
            

        }
        log.debug("消息消费-发送公众号模版消息处理结束");
    }

原代码存在问题:

  1. 在增加新的消息类型时,需要同步修改消息发送控制器,在switch语句里增加新的case子语句。
  2. 两边的修改不是同步的,容易导致修改遗漏,比如只修改了消息的类型枚举,而没有修改消息的发送控制器。

优化后的代码

消息类型的枚举:



public enum WxocTemplateMessageTypeEnum {

    /**
     * 电话访谈活动开始之前
     */
    BEFORE_TELEPHONE_INTERVIEW_ACTIVITY_START(
        (api,wxocUserId,form)->api.sendBeforeTelephoneInterviewTemplateMessage(wxocUserId,form)),


    /**
     * 路演活动开始之前
     */
    BEFORE_ROAD_SHOW_ACTIVITY_START(
        (api,wxocUserId,form)->api.sendBeforeRoadShowActivityStartTemplateMessage(wxocUserId,form)),

    /**
     * 会议结束通知
     */
    ACTIVITY_END(
        (api,wxocUserId,form)->api.sendActivityEndTemplateMessage(wxocUserId,form)),

    /**
     * 会议取消通知
     */
    ACTIVITY_CANCEL(
        (api,wxocUserId,form)->api.sendActivityCancelTemplateMessage(wxocUserId,form)),


    /**
     * 收款到账通知
     */
    RECEIPT_OF_ACCOUNT(
        (api,wxocUserId,form)->api.sendReceiptOfAccountTemplateMessage(wxocUserId,form)),






    ;

    /**
     * 消息发送器
     */
    private SendMessageHandler sendMessageHandler;

    private WxocTemplateMessageTypeEnum(SendMessageHandler handler){
        this.sendMessageHandler = handler;
    }

    /**
     * 发送消息
     * @param innerProjectWxocApi
     * @param wxocUserId
     * @param templateMessageForm
     * @return void
     */
    public void sendMessage(InnerProjectWxocApi innerProjectWxocApi, Integer wxocUserId,WxocTemplateMessageForm templateMessageForm){
        this.sendMessageHandler.sendMessage(innerProjectWxocApi,wxocUserId,templateMessageForm);
    }


    /**
     * 发送消息处理器接口
     */
    private interface SendMessageHandler{
        /**
         * 发送消息的方法
         * @param innerProjectWxocApi
         * @param wxocUserId
         * @param templateMessageForm
         * @return void
         */
        void sendMessage(InnerProjectWxocApi innerProjectWxocApi, Integer wxocUserId,WxocTemplateMessageForm templateMessageForm);
    }


}


消息控制器发送消息的方法


 private void sendWxoxTemplateMessage(MessageTypeEnum type,ISystemMessageConsumerService messageConsumer
        ,String body){
        log.debug("消息消费-发送公众号模版消息处理开始");
        if(type.isSendWxoxTemplateMessage()){
            //获取消息模版类型
            WxocTemplateMessageTypeEnum templateMessageTypeEnum = messageConsumer.getWxocTemplateMessageTypeEnum(body);
            if(templateMessageTypeEnum==null){
                log.debug("消息消费-发送公众号模版消息-未知的消息类型");
                return ;
            }
            WxocTemplateMessageForm templateMessageForm = messageConsumer.generateWxocTemplateMessageForm(body);
            if(templateMessageForm==null){
                log.debug("消息消费-发送公众号模版消息-生成消息模版失败");
                return ;
            }
            Integer wxocUserId = messageConsumer.getWxocUserId(body);
            if(wxocUserId==null){
                log.debug("消息消费-发送公众号模版消息-没有有效的微信公众号用户");
                return ;
            }
            templateMessageTypeEnum.sendMessage(innerProjectWxocApi,wxocUserId,templateMessageForm);
        }
        log.debug("消息消费-发送公众号模版消息处理结束");
    }

优化说明:

  1. 定义了一个SendMessageHandler 接口,该接口只提供了一个sendMessage的方法,按照Java语法,只有一个方法的接口称之为函数接口
  2. 为什么要定义函数接口?,因为Java自带的函数接口没有支持传3个参数的,所以需要自己定义一个。
  3. 在枚举的构造函数里增加了SendMessageHandler接口实现的参数,用于指定每个枚举的消息具体的消息发送处理方法。
  4. 构造枚举时,指定当前枚举的实际执行的api的具体的方法。
  5. 为每个枚举提供一个发送消息的方法,用于调用SendMessageHandler的实现。
  6. 消息控制器只需要拿到本次待发送消息的枚举,直接调用枚举的发送消息的方法,传入对应的参数即可。