• 采用C#泛型实现状态(State)模式



    一、问题来源

    目前时兴这样的应用:用户采用Jabber(一种开源即时通讯协议)客户端登录Jabber服务器,然后再经过MSN中转站,就可以与MSN用户通讯了。系统结构如下:

     

    其中中转服务器实现协议翻译。假设存在这样一种情况,就是客户端和中转服务器采用的不是那种双向通讯,而是如Html这样单向通讯手段(假设不用Ajax),客户端没有存储能力,因此需要把信息存储在中转服务器的数据库中。中转服务器的流量很大,当接收到信息或者用户阅读未读信息后,不能实时进行数据库的Insert和Update操作,而是定期轮询,进行批量处理。

    中转服务器将消息存储在消息容器中。线程模型如下:

     


    主要有三类线程:

    (1)服务器监听线程监听来自第三方服务器的数据包,解析成消息对象,存储在消息容器中。
    (2)用户服务线程根据用户的请求,取出消息,发送给用户,同时改变消息的状态,如果消息为“未读”,则改变为“已读”。
    (3)数据库同步线程定期检查所有消息,根据消息状态,判断客户端的消息状态是否和数据库中储存的状态一致,如果不一致,则进行Update操作,如果数据库中不存在,则进行Insert操作。

    消息一共有五种状态:

              客户端是否已读    数据库中存储的状态      需要Update    需要Insert操作
    状态1            已读                已读               否            否
    状态2            已读                未读               是            否
    状态3            未读                未读               否            否
    状态4            未读                无                 否            是
    状态5            已读                无                 否            是

    用户阅读信息以及数据库同步操作可能导致用户状态改变。状态图如下:

     

    二、实现

    先给状态取名字:

        状态1:SReadedCReadedState
        状态2:SUnreadCReadState
        状态3:SUnreadCUnreadState
        状态4:SUnsavedCUnreadState
        状态5:SUnsavedCReadedState

    根据《设计模式》书中的State模式,实现如下:


      1     public interface IMsgState
      2     {
      3         void MaskReaded(IMessage msg);  // 标为已读
      4         void MaskSaved(IMessage msg);   // 标为同步
      5         Boolean NeedInsert { get; }     // 是否Insert
      6         Boolean NeedUpdate { get;}      // 是否Update
      7         Boolean Readed { get;}          // 是否已读
      8     }
      9 
     10     public interface IMessage
     11     {
     12         void MaskReaded();
     13 
     14         void MaskSaved();
     15 
     16         Boolean NeedInsert { get; }
     17 
     18         Boolean NeedUpdate { get;}
     19 
     20         Boolean Readed { get;} 
     21 
     22         void ChangeState(IMsgState newState);
     23     }
     24 
     25     public class Message : IMessage
     26     {
     27         private IMsgState state;
     28 
     29         public Message(IMsgState initState)
     30         {
     31             state = initState;
     32         }
     33 
     34         #region IMessage 成员
     35 
     36         public void MaskReaded()
     37         {
     38             state.MaskReaded(this);
     39         }
     40 
     41         public void MaskSaved()
     42         {
     43             state.MaskSaved(this);
     44         }
     45 
     46         public bool NeedInsert
     47         {
     48             get { return state.NeedInsert; }
     49         }
     50 
     51         public bool NeedUpdate
     52         {
     53             get { return state.NeedUpdate; }
     54         }
     55 
     56         public bool Readed
     57         {
     58             get { return state.Readed; }
     59         }
     60 
     61         public void ChangeState(IMsgState newState)
     62         {
     63             this.state = newState;
     64         }
     65 
     66         #endregion
     67     }
     68 
     69     public class SReadedCReadedState : IMsgState
     70     {
     71         private static SReadedCReadedState instance = new SReadedCReadedState();
     72         public static SReadedCReadedState Instance
     73         {
     74             get { return instance; }
     75         }
     76 
     77         #region IMsgState 成员
     78 
     79         public void MaskReaded(IMessage msg)
     80         {
     81             msg.ChangeState(SReadedCReadedState.Instance);
     82         }
     83 
     84         public void MaskSaved(IMessage msg)
     85         {
     86             msg.ChangeState(SReadedCReadedState.Instance);
     87         }
     88 
     89         public bool NeedInsert
     90         {
     91             get { return false; }
     92         }
     93 
     94         public bool NeedUpdate
     95         {
     96             get { return false; }
     97         }
     98 
     99         public bool Readed
    100         {
    101             get { return true; }
    102         }
    103 
    104         #endregion
    105     }
    106 
    107     public class SUnreadCUnreadState : IMsgState
    108     {
    109         private static SUnreadCUnreadState instance = new SUnreadCUnreadState();
    110         public static SUnreadCUnreadState Instance
    111         {
    112             get { return instance; }
    113         }
    114 
    115         #region IMsgState 成员
    116 
    117         public void MaskReaded(IMessage msg)
    118         {
    119             msg.ChangeState(SUnreadCReadState.Instance);
    120         }
    121 
    122         public void MaskSaved(IMessage msg)
    123         {
    124             msg.ChangeState(SUnreadCUnreadState.Instance);
    125         }
    126 
    127         public bool NeedInsert
    128         {
    129             get { return false; }
    130         }
    131 
    132         public bool NeedUpdate
    133         {
    134             get { return false; }
    135         }
    136 
    137         public bool Readed
    138         {
    139             get { return false; }
    140         }
    141         #endregion
    142     }
    143 
    144     public class SUnreadCReadState : IMsgState
    145     {
    146         private static SUnreadCReadState instance = new SUnreadCReadState();
    147         public static SUnreadCReadState Instance
    148         {
    149             get { return instance; }
    150         }
    151 
    152         #region IMsgState 成员
    153 
    154         public void MaskReaded(IMessage msg)
    155         {
    156             msg.ChangeState(SUnreadCReadState.Instance);
    157         }
    158 
    159         public void MaskSaved(IMessage msg)
    160         {
    161             msg.ChangeState(SReadedCReadedState.Instance);
    162         }
    163 
    164         public bool NeedInsert
    165         {
    166             get { return false; }
    167         }
    168 
    169         public bool NeedUpdate
    170         {
    171             get { return true; }
    172         }
    173 
    174         public bool Readed
    175         {
    176             get { return true; }
    177         }
    178 
    179         #endregion
    180     }
    181 
    182     public class SUnsavedCUnreadState : IMsgState
    183     {
    184         private static SUnsavedCUnreadState instance = new SUnsavedCUnreadState();
    185         public static SUnsavedCUnreadState Instance
    186         {
    187             get { return instance; }
    188         }
    189 
    190         #region IMsgState 成员
    191 
    192         public void MaskReaded(IMessage msg)
    193         {
    194             msg.ChangeState(SUnsavedCReadedState.Instance);
    195         }
    196 
    197         public void MaskSaved(IMessage msg)
    198         {
    199             msg.ChangeState(SUnreadCUnreadState.Instance);
    200         }
    201 
    202         public bool NeedInsert
    203         {
    204             get { return true; }
    205         }
    206 
    207         public bool NeedUpdate
    208         {
    209             get { return false; }
    210         }
    211 
    212         public bool Readed
    213         {
    214             get { return false; }
    215         }
    216 
    217         #endregion
    218     }
    219 
    220     public class SUnsavedCReadedState : IMsgState
    221     {
    222         private static SUnsavedCReadedState instance = new SUnsavedCReadedState();
    223         public static SUnsavedCReadedState Instance
    224         {
    225             get { return instance; }
    226         }
    227 
    228         #region IMsgState 成员
    229 
    230         public void MaskReaded(IMessage msg)
    231         {
    232             msg.ChangeState(SUnsavedCReadedState.Instance);
    233         }
    234 
    235         public void MaskSaved(IMessage msg)
    236         {
    237             msg.ChangeState(SReadedCReadedState.Instance);
    238         }
    239 
    240         public bool NeedInsert
    241         {
    242             get { return true; }
    243         }
    244 
    245         public bool NeedUpdate
    246         {
    247             get { return false; }
    248         }
    249 
    250         public bool Readed
    251         {
    252             get { return true; }
    253         }
    254 
    255         #endregion
    256 

    假定消息存储在 IList<IMessage> msgs 之中,用户阅读操作:

    1         void Read(IMessage msg)
    2         {
    3             //  do read, then:
    4             msg.MaskReaded();
    5         }
    6 

    同步操作:

     1         void Save()
     2         {
     3             foreach (IMessage msg in msgs)
     4             {
     5                 if (msg.NeedInsert)
     6                 {
     7                     // insert 
     8                 }
     9                 if (msg.NeedUpdate)
    10                 {
    11                     // update
    12                 }
    13 
    14                 msg.MaskSaved();
    15             }
    16         }
    17 

    三、泛型实现

    上面的实现太长了,并且状态相关的逻辑分布在各个类之中,相隔太远,容易写错。下面试试用泛型实现。

    鉴于 C#2.0泛型不能用值作为参数类型(郁闷!!!!!!!!),因此首先需要把bool和false构造成类型:

     1     public interface IValueType<ValueType>
     2     {
     3         ValueType Value { get;}
     4     }
     5 
     6     public class TrueType : IValueType<bool>
     7     {
     8         public bool Value { get { return true; } }
     9     }
    10 
    11     public class FalseType : IValueType<bool>
    12     {
    13         public bool Value { get { return false; } }
    14     }
    15 

    实现State模式:

      1     public interface IMsgState
      2     {
      3         void MaskReaded(IMessage msg);  // 标为已读
      4         void MaskSaved(IMessage msg);   // 标为同步
      5         Boolean NeedInsert { get; }     // 是否Insert
      6         Boolean NeedUpdate { get;}      // 是否Update
      7         Boolean Readed { get;}          // 是否已读
      8     }
      9 
     10     public interface IMessage
     11     {
     12         void MaskReaded();
     13 
     14         void MaskSaved();
     15 
     16         Boolean NeedInsert { get; }
     17 
     18         Boolean NeedUpdate { get;}
     19 
     20         Boolean Readed { get;}
     21 
     22         void ChangeState(IMsgState newState);
     23     }
     24 
     25     public class Message : IMessage
     26     {
     27         private IMsgState state;
     28 
     29         public Message(IMsgState initState)
     30         {
     31             state = initState;
     32         }
     33 
     34         #region IMessage 成员
     35 
     36         public void MaskReaded()
     37         {
     38             state.MaskReaded(this);
     39         }
     40 
     41         public void MaskSaved()
     42         {
     43             state.MaskSaved(this);
     44         }
     45 
     46         public bool NeedInsert
     47         {
     48             get { return state.NeedInsert; }
     49         }
     50 
     51         public bool NeedUpdate
     52         {
     53             get { return state.NeedUpdate; }
     54         }
     55 
     56         public bool Readed
     57         {
     58             get { return state.Readed; }
     59         }
     60 
     61         public void ChangeState(IMsgState newState)
     62         {
     63             this.state = newState;
     64         }
     65 
     66         #endregion
     67     }
     68 
     69     public class MsgState
     70         <MaskReadedToType, MaskSavedToType, 
     71         NeedInsertValueType, NeedUpdateValueType,
     72         ReadedValueType>
     73     : IMsgState
     74         where MaskReadedToType : IMsgState, new()
     75         where MaskSavedToType : IMsgState, new()
     76         where NeedInsertValueType : IValueType<bool>new()
     77         where NeedUpdateValueType : IValueType<bool>new()
     78         where ReadedValueType : IValueType<bool>new()
     79     {
     80         #region IMsgState 成员
     81 
     82         public void MaskReaded(IMessage msg)
     83         {
     84             msg.ChangeState(new MaskReadedToType());
     85         }
     86 
     87         public void MaskSaved(IMessage msg)
     88         {
     89             msg.ChangeState(new MaskSavedToType());
     90         }
     91 
     92         #endregion
     93 
     94         #region IMsgState 成员
     95 
     96 
     97         public bool NeedInsert
     98         {
     99             get { return new NeedInsertValueType().Value; } 
    100         }
    101 
    102         public bool NeedUpdate
    103         {
    104             get { return new NeedUpdateValueType().Value; } 
    105         }
    106 
    107         public bool Readed
    108         {
    109             get { return new ReadedValueType().Value; } 
    110         }
    111 
    112         #endregion
    113     }
    114 
    115     public class SReadedCReadedState:
    116         MsgState<SReadedCReadedState, SReadedCReadedState, 
    117         FalseType, FalseType, TrueType> { }
    118 
    119     public class SUnreadCUnreadState:
    120         MsgState<SUnreadCReadState, SUnreadCUnreadState, 
    121         FalseType, TrueType, FalseType> { }
    122 
    123     public class SUnreadCReadState:
    124         MsgState<SUnreadCReadState, SReadedCReadedState, 
    125         FalseType, FalseType, TrueType> { }
    126 
    127     public class SUnsavedCUnreadState:
    128         MsgState<SUnsavedCReadedState, SUnreadCUnreadState, 
    129         TrueType, FalseType, FalseType> { }
    130 
    131     public class SUnsavedCReadedState:
    132         MsgState<SUnsavedCReadedState, SReadedCReadedState,
    133         TrueType, FalseType, TrueType> { }
    134 

    其余操作同上:

     1         void Read(IMessage msg)
     2         {
     3             //  do read, then:
     4             msg.MaskReaded();
     5         }
     6 
     7         void Save()
     8         {
     9             foreach (IMessage msg in msgs)
    10             {
    11                 if (msg.NeedInsert)
    12                 {
    13                     // insert 
    14                 }
    15                 if (msg.NeedUpdate)
    16                 {
    17                     // update
    18                 }
    19 
    20                 msg.MaskSaved();
    21             }
    22         }
    23 

    四、小结

    由上可见,采用泛型实现的State模式代码量比不采用泛型实现的要少,更大的优点是,泛型实现中各种状态的定义比较短,这些定义可以放在一起,这样写起来也不容易写错,维护起来也比较简单。

    (以上代码编译通过,逻辑上正确性与否我没验证----嘿嘿,事情讲清楚就可以了......)

    作者:兽族的荣耀:xiaotie at gmail dot com; http://xiaotie.cnblogs.com

    版权所有,欢迎转载
  • 相关阅读:
    每日总结3.8
    Go中定时器实现原理及源码解析
    Go语言实现布谷鸟过滤器
    详解Go语言调度循环源码实现
    Go语言中时间轮的实现
    详解Go语言I/O多路复用netpoller模型
    详解Go中内存分配源码实现
    Go中由WaitGroup引发对内存对齐思考
    【分享】java精品实战教程
    nginx实战教程
  • 原文地址:https://www.cnblogs.com/xiaotie/p/595209.html
Copyright © 2020-2023  润新知