业务场景:设备和客户端按照通讯协议进行通信,设备会有大量的消息送到到客户端,然后客户端收到消息并进行解析,根据不同的消息类型进行区分处理。

如果不考虑设计模式,不考虑易扩展性和易维护性,通常我们的代码会是如下情况:

/// <summary>
        /// 设备消息送到解析
        /// </summary>
        /// <param name="MsgType"></param>
        private void ExplainData(ushort MsgType)
        {
            switch (MsgType)
            {
                case (ushort)EMMsgType.LogSerialNumSever: //登录序号
                    //处理当前的业务
                    break;
                case (ushort)EMMsgType.LogResultServer: //登录结果
                    //处理这里的业务
                    break;
                case (ushort)EMMsgType.ResultPhoneCallMoney://电召费用查询结果返回
                    if (条件1)
                    {
                        //处理这里的业务
                    }
                    else
                    {
                        //处理这里的业务
                    }
                    if (条件2)
                    {
                        //又处理其他情况
                    }
                    else
                    {
                        //处理这里的业务
                    }
                    break;
            }
        }

如果协议中的设备消息有100种,那我们自然就当前switch里面会包含100个case,每个case之间又会还有相关的业务代码。

真实代码片段是这样的

CodeSys Switch_CodeSys Switch

这个switch里面包含了522行代码,如果需要修改或增加新的业务功能,需要在522行代码里面小心的增加已避免对其他case里的代码造成影响。其维护难度太大了。

如何考虑代码优化

客户端接收到消息-》处理消息。我们增加一个消息处理接口类。

public interface BaseExplainData
    {
        /// <summary>
        /// 数据解析
        /// </summary>
        /// <param name="msgData"></param>
        void ExplainData();

    }

 

 增加实现了消息处理基类的具体实现类

public class 设置终端参数处理类:BaseExplainData
    {
        public void ExplainData()
        {
            Console.WriteLine("这里是设置终端参数处理类");
            //其他处理
        }
    }

    public class 平台返回心跳处理类 : BaseExplainData
    {
        public void ExplainData()
        {
            Console.WriteLine("这里是平台返回心跳处理类");
            //其他处理
        }
    }

    public class 客服端心跳包处理类 : BaseExplainData
    {
        public void ExplainData()
        {
            Console.WriteLine("这里是客服端心跳包处理类");
            //其他处理
        }
    }

    public class 终端通用应答处理类 : BaseExplainData
    {
        public void ExplainData()
        {
            Console.WriteLine("这里是终端通用应答处理类");
            //其他处理
        }
    }

增加个字典(字典由于有key,所以是高效查找),key是消息类型,对应的保存的是该消息的实例化的消息处理类。

public Dictionary<EMMsgType, BaseExplainData> dicExplainReceiveData = new Dictionary<EMMsgType, BaseExplainData>
        {
            {EMMsgType.终端通用应答,new 终端通用应答处理类()},
            {EMMsgType.客服端心跳包,new 客服端心跳包处理类()},
            {EMMsgType.平台返回心跳,new 平台返回心跳处理类()},
            {EMMsgType.设置终端参数,new 设置终端参数处理类()},
            //如果以后有增加其他消息处理,就在后面追加
        };

如果后续又增加了其他的消息协议,因为字典里的对象是平行关系,只需要在字典里追加。简单直接。

最后的处理代码,设备消息过来,根据消息类型从字典里取出实例化的对象,调用ExplainData处理。

1         /// <summary>
 2         /// 设备消息送到解析
 3         /// </summary>
 4         /// <param name="MsgType"></param>
 5         private void ExplainData(EMMsgType MsgType)
 6         {
 7             var rst=dicExplainReceiveData[MsgType];
 8             if (rst!=null)
 9             {
10                 rst.ExplainData();
11             }
12         }

如果后续又增加了其他的消息协议,这里完全不用修改。

代码简洁清晰,再也不用看switch..case...case...case...^0^