采用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模式,实现如下:
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 之中,用户阅读操作:
2 {
3 // do read, then:
4 msg.MaskReaded();
5 }
6
同步操作:
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构造成类型:
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模式:
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
其余操作同上:
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
本文转自xiaotie博客园博客,原文链接http://www.cnblogs.com/xiaotie/archive/2006/12/18/595209.html如需转载请自行联系原作者
xiaotie 集异璧实验室(GEBLAB)
采用C#泛型实现状态(State)模式相关推荐
- 设计模式:状态(State)模式
设计模式之状态(State)模式 在软件开发过程中,应用程序中的有些对象可能会根据不同的情况做出不同的行为,我们把这种对象称为有状态的对象,而把影响对象行为的一个或多个动态变化的属性称为状态.当有状态 ...
- 设计模式学习笔记——状态(State)模式框架
设计模式学习笔记--状态(State)模式框架 @(设计模式)[设计模式, 状态模式, State] 设计模式学习笔记状态State模式框架 基本介绍 状态案例 类图 实现代码 State接口 Day ...
- 设计模式--状态(State)模式
模式定义 允许一个对象在其内部状态改变时改变它的行为,从而使对象看起来似乎修改了其行为 类图 要点总结 State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时, ...
- 状态(State)模式
状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改变其行为.这个对象看上去就像是改变了它的 ...
- C++之状态(State)模式
0. 简介 状态模式是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样.这其实就有点类似算法中的有限状态机的形式. 其主要思想是程序在任意时刻仅可 ...
- 状态转移表+State模式
为了给用户提供更好的体验方式,多级联动,多种选择方式,半智能化的容错能力等是我们采用的手段,同时这对软件的开发带来了更多的复杂性.我们需要考虑在各种不同状态下,按钮的功能,以及转换. 在我做过的若干项 ...
- java state用法_Java状态模式(State模式)
State的定义:不同的状态,不同的行为:或者说,每个状态有着相应的行为. 何时使用状态模式State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elsei ...
- 理解vuex -- vue的状态管理模式
2019独角兽企业重金招聘Python工程师标准>>> vuex是什么? 先引用vuex官网的话: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管 ...
- Android学习 StateMachine与State模式
2019独角兽企业重金招聘Python工程师标准>>> 一 State模式 意图: 允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类.(Objects for ...
- [设计模式][c++]状态切换模式
转自:http://blog.csdn.net/yongh701/article/details/49154439 状态模式也是设计模式的一种,这种设计模式思想不复杂,就是实现起来的代码有点复杂.主要 ...
最新文章
- 苗旺:因果推断,观察性研究和 2021 年诺贝尔经济学奖
- 被劝退的学渣,逆袭成高级语言之父,改变编程方式却说“不喜欢写代码”!...
- CentOS7下搭建Nextcloud13.0.5
- JavaScript中类型检测
- VTK修炼之道53:图形基本操作进阶_多分辨率策略(模型细化的三种方法)
- 自定义ViewGroup(1)
- 博客社会学图——使用python检索网页上的友情链接
- 关于导航按钮在其他尺寸下显示问题
- Beta版本测试报告
- linux nslookup命令安装,在CentOS中安装nslookup命令
- k-近邻算法-优化约会网站的配对效果
- 均值聚类散点图怎么画_用Excel制作一个漂亮的分类散点图
- UNI/TUBE2新配对上线,Eswap迎来新机遇
- 情商 智商 逆商,哪个最重要?
- U8glib学习使用(详细版)
- 2021年国产数据库名录和产品信息一览
- mysql5.7 1698 28000_MySqlError1698(28000)问题的解决方法
- 什么是 CDP 和 LLDP?
- 去除COD有机物树脂A-722MP
- C语言中的TRUE和FALSE
热门文章
- Android Multimedia框架总结(一)MediaPlayer介绍之状态图及生命周期
- python变量、运算符、要求从键盘输入用户名和密码,校验格式是否符合规则,如果不符合,打印出不符合的原因,并提示重新输入练习
- 长春理工大学计算机科学与技术学分,计算机科学与技术专业本科人才培养方案-长春理工大学教务处.PDF...
- 红旗Linux职称考试模块,计算机职称考试红旗Linux Desktop 6.0考试大纲
- java脚本计算器按钮无反应_2020年3月份最新计算机语言排行,20种语言争锋相对Java依旧飘逸...
- 自定义日历控android,android 一个简单的自定义日历控件,让你掌控时间
- 2层框架结构柱子间距_钢筋混凝土楼板层其施工方法有哪些不同
- python两数之和是多少_Python面试:两数之和
- ip代理服务器8需要云速捷_nginx获取真实ip,proxy_set_head怎么设置头部信息
- android activity根节点addview_Android嵌入到页面中的加载动画工具类