采用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               //  dot.gif 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 dot.gif
 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               //  dot.gif 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 dot.gif
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

转载于:https://www.cnblogs.com/xiaotie/archive/2006/12/18/595209.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值