zoukankan      html  css  js  c++  java
  • 最近重构一个通讯系统 想了一个很有趣的设计模式,我就叫——移花接木

     

    最近在重构通讯系统,最难处理的就是传输协议。一个普通的系统,最核心的协议也最少有10多种。

     

    我自然会使用面向对象去做,而不是用StringBuilder之类的去拼、去解析。

     

    按照普通的面向对象思路,有两种方案:

     

    1. 第一个失败方案:每个协议一个对象,例如:

     

    代码
            interface IAddContact
            {
                
    string Guid { get;}
                
    string MessageId { get;}
                
    string ConnectorIdentifier { get;}
                
    string ReceiverCode { get;}
            }

            
    interface IBind
            {
                
    string Command { get;}
                
    string Guid { get;}
                
    string SenderName { get; }
                
    string MessageId { get;}
                MessageflowLevel LevelType { 
    get;}
                
    string ReceiverCode { get;}
                
    string ReceiverName { get;}
                
    string ConnectorIdentifier { get;}
            }

     

    可是这种方式的最恶心的地方在于,没有一个统一的基接口,导致处理逻辑复杂;一个协议就一个对象+一个接口。在系统中,当字符串被传递过来的时候,解析(反序列化)起来就非常麻烦。

     

    比方说,有50%的协议使用了GUID,而另外50%的使用了MessageId等等。但是协议之间又无法提取公共的interface。那么实际的处理程序就需要一个个去判断反序列化了。超级恶心。

     

    2. 第二个失败方案是使用一个总的对象,他包含了所有协议使用的字段:

     

    代码
        public interface IMessageflowMessage : IMessage
        {
            
    string Command { get;}
            MessageflowLevel LevelType { 
    get;}
            MessageflowCommand CommandType { 
    get;}
            
    string ConnectorIdentifier { get;}
            
    string Guid { get;}
            
    string Token { get;}
            
    string MessageId { get;}
            
    string ReceiverCode { get;}
            
    string ReceiverName { get;}
            
    string SenderName { get; }
            
    string Message { get; }
    。。。。。。。。。(其他字段)。。。。。。。。。。。。。
            
    string Serialize();
        }

     

    这个方案虽然可以对所有协议进行了统一的对象化,可是实际编码起来,我又发现了另外一个问题:由于不同的协议需要使用的字段不一样,那么一个处理模块可能仅仅需要10%的字段;这样我就发现我陷入了一个遗忘的陷阱,经常忘记某个协议的关键字段是什么。

    虽然我可以通过写文档去帮助我开发,可是在不断修改的过程中,协议会经常变动,这样开发精力放在了2头(维护文档和代码),得不偿失。

     

    于是我今天起床吃饭的时候,用了1个小时去思考,终于得到了一个设计模式——移花接木

    这个模式的特点是结合了2种方案,具体如下:

     

    代码
    interface IMessageflowMessage
    {
        
    //这是个协议模板 可能包含了上百种属性字段
        string GUID {get;set;}
        
    string MessageID {get;set;}
    }

    class MessageflowMessage : IMessageflowMessage
    {
        
    //协议模板的具体实现类
        public string GUID
        {
        get { return guid; } set { guid = value; }
        }

        
    public string MessageID
        {
        get { return messageId; } set { messageId = value; }
        }

    }


    interface IAddContact
    {
        
    //这是个具体的协议,仅仅包含了少数的属性字段
         string GUID {get;set;}
    }

    class AddContact : MessageflowMessage, IAddContact
    {
        
    //这个是某个具体协议接口的实现,要注意,这里实际上没有代码
    }

     

    就这么简单!!!在这超级漂亮的模式中,

     

    首先,有个基本的协议模板,MessageflowMessage,他包含了所有的协议字段。

    其次,具体要调用的协议 AddContact又继承了MessageflowMessage,因此这个class是不需要任何代码的。

    再次,AddContact又继承了接口IAddContact,用户实际使用过程中,仅仅需要了解GUID这个字段,其他字段都被“屏蔽”了。

     

    最后,我为什么叫这个是移花接木呢?很简单,我调用的代码是:

     

    string message = "xxxxxxxxxxxxxxx";
    IAddContact protocol = Deserialize<AddContact>(message);

    首先对传入的字符串协议,反序列化为AddContact对象,然而这个对象本身没有任何代码,都是继承了MessageflowMesasge。

     

    其次,这个AddContact对象又会被我以IAddContact接口形式返回,这样逻辑上就出现了一个非常有趣的现象:

    协议模板和我返回的接口在代码上是没有任何关系的(MessageflowMessage / IMessageflowMessage 和 IAddContact);但是他们通过了一个空的类(AddContact)联系在了一起,因此被移花接木了!

     

    这种设计模式下,我只要规定了协议模板(MessageflowMessage)之后,只要这个模板足够强大,那么日后我可以扩展出任意的协议,但是却不需要修改原来的解析引擎了。

     

    不知道大家觉得怎么样?

  • 相关阅读:
    Civil 3D 二次开发 创建Civil 3D 对象—— 01 —— 创建几何空间点
    Civil 3D 二次开发 创建Civil 3D 对象—— 00 ——
    Civil 3D 二次开发 创建AutoCAD对象—— 01 —— 创建直线
    Civil 3D 二次开发 新建CLR项目出现错误C2143
    Civil 3D 二次开发 创建AutoCAD对象—— 00 ——
    了解AutoCAD对象层次结构 —— 6 ——块表记录
    datepicker97使用
    使用angular 外接 templateUrl,使用ng-include
    angularJs 遮罩
    网上找的有关css兼容问题
  • 原文地址:https://www.cnblogs.com/zc22/p/1730821.html
Copyright © 2011-2022 走看看