<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Memento..</title><subtitle type="text">My stories in my way..</subtitle><id>http://feed.cnblogs.com/blog/u/49902/rss</id><updated>2011-12-31T04:54:32Z</updated><author><name>流牛木马</name><uri>http://www.cnblogs.com/azure/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/azure/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/49902/rss"/><entry><id>http://www.cnblogs.com/azure/archive/2011/12/31/Dota_MVP.html</id><title type="text">程序猿的逆袭-Dota玩什么英雄最容易拿MVP？</title><summary type="text">相信很多“牛人”都被一些宅男学弟问过这个问题：学长，我作为一个初学程序的菜鸟，要怎么样才能提交自己的编程水平，变成牛人呢？本文就以“统计Dota玩什么英雄最容易拿MVP”为例，做一次抛砖引玉。</summary><published>2011-12-31T04:49:00Z</published><updated>2011-12-31T04:49:00Z</updated><author><name>流牛木马</name><uri>http://www.cnblogs.com/azure/</uri></author><link rel="alternate" href="http://www.cnblogs.com/azure/archive/2011/12/31/Dota_MVP.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/azure/archive/2011/12/31/Dota_MVP.html"/><content type="html">&lt;p&gt;&lt;/p&gt; &lt;p&gt;相信很多&amp;#8220;牛人&amp;#8221;都被一些宅男学弟问过这个问题：学长，我作为一个初学程序的菜鸟，要怎么样才能提交自己的编程水平，变成牛人呢？&lt;/p&gt; &lt;p&gt;说实话，这个问题深奥地我有点回答不上来，无外乎只能告诉他&amp;#8220;多读&amp;#8221;&amp;#8220;多写&amp;#8221;&amp;#8220;搞好数学和算法，练内功&amp;#8221;&amp;#8220;用好设计模式&amp;#8221;&amp;#8220;看《编程之美》&amp;#8221;等等之类的空话套话。后来&lt;a href="http://weibo.com/artyyouth" target="_blank"&gt;剃刀阿遠&lt;/a&gt;给出了一个答案让我深受启迪，他说：就一句话&amp;#8212;&amp;#8212;&lt;strong&gt;多写给人用的代码&lt;/strong&gt;。&lt;/p&gt; &lt;p&gt;这句话第一次听上去也许觉得有点装逼，实则不然，我非常认同这个观点。&lt;/p&gt; &lt;p&gt;好吧，宅男学弟又开始问了：学长，什么样的代码才是给人用的代码？毕竟我一个菜鸟我又不是腾讯不能弹窗口邀请别人来用，别人为什么要用一个菜鸟的代码呢？&lt;/p&gt; &lt;p&gt;这个问题相对就更非常具体了，我个人认为，&lt;strong&gt;有实用价值同时又让人觉得亲切有趣&lt;/strong&gt;的程序就可以了。&lt;/p&gt; &lt;p&gt;例如，Dota是一款80后程序猿耳熟能详的游戏，尤其是还没走出大学校门的挨踢宅男的最爱。毫无疑问，如果我们以Dota作为突破点，只要idea有意思、跟Dota紧密相关，就算是菜鸟写的程序也能在学校BBS里被大家争相传阅。&lt;/p&gt; &lt;p&gt;本文就以&amp;#8220;统计Dota玩什么英雄最容易拿MVP&amp;#8221;为例，做一次抛砖引玉。文末我们可以讨论更多关于Dota辅助程序的idea。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;11对战平台是最近流行的Dota平台，与其他对战平台不同的是，11有海量的统计数据。对于每一个玩家，都有最详细的统计，细到包括他所擅长的英雄、历史上用哪个英雄做了哪些事、平均某个英雄出场杀敌数、甚至细到该玩家历史上一共拿了多少个Double Kill都有记录。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/201112/20111231124816567.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/201112/201112311248244914.png" width="854" height="461" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;本文仅仅示例如何统计MVP而已，相对于11对战平台的数据宝库来说，可谓是&amp;#8220;弱水三千，只取一瓢&amp;#8221;。思路是这样的： 抓取大量（如十万个）活跃玩家的历史场次信息，对所有场次的MVP英雄进行统计。十万个活跃玩家涉及的总Dota场次是千万级的，统计样本已经很充足。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;有了基本思路，我们再理一个详尽的流程：&lt;/p&gt; &lt;p&gt;1.抓取数据并保存到本地。（涉及的新手知识：如何抓取网络数据包、 通过WebClient下载HTML网页）&lt;/p&gt; &lt;p&gt;2.分析已保存到本地的数据，作出记录。（涉及的新手知识：简单的正则表达式、处理JSON）&lt;/p&gt; &lt;p&gt;3.制作直观统计结果（涉及的新手知识：LINQ和lambda表达式、文件的读写）&lt;/p&gt; &lt;p&gt;这么一个简单的程序，对初学.NET的新手来讲，可以带着兴趣锻炼到如此多的基本功知识点，比看什么枯燥的xxx入门到精通书籍有趣多了！ o(&amp;#8745;_&amp;#8745;)o&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;第一步 用Fiddler抓包获得用户统计页面的URL&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/201112/201112311248341053.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/201112/201112311248432784.png" width="804" height="494" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;通过抓包我们知道：&lt;/p&gt; &lt;p&gt;1.用户统计页面的地址形如：&lt;/p&gt;&lt;a title="http://i.5211game.com/rating/?u=4629868&#xD;
" href="http://i.5211game.com/rating/?u=4629868"&gt;http://i.5211game.com/rating/?u=4629868&lt;br /&gt;&lt;/a&gt; &lt;p&gt;u后面是用户的ID&lt;/p&gt; &lt;p&gt;2.需要登录才能查看统计结果。我们程序获取页面时，可以通过设置Cookie来模拟登录。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;第二步 使用WebClient构造请求&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;Cookie部分设置为Fiddler里所抓取到的Cookie值。如果抓取成功就保存到本地文件，文件名以用户ID命名。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;抓取某个玩家的数据o&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param&amp;nbsp;name="i"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;玩家平台的ID&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&amp;nbsp;GetFiles(&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&amp;nbsp;i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WebClient&amp;nbsp;wc&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;WebClient();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wc.Headers.Add(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;User-Agent&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Mozilla/5.0&amp;nbsp;(Windows&amp;nbsp;NT&amp;nbsp;6.1)&amp;nbsp;AppleWebKit/535.1&amp;nbsp;(KHTML,&amp;nbsp;like&amp;nbsp;Gecko)&amp;nbsp;Chrome/14.0.835.186&amp;nbsp;Safari/535.1&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wc.Headers.Add(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Accept&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wc.Headers.Add(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Accept-Encoding&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;gzip,deflate,sdch&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wc.Headers.Add(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Accept-Language&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;zh-CN,zh;q=0.8&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wc.Headers.Add(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Accept-Charset&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;nbsp;GBK,utf-8;q=0.7,*;q=0.3&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wc.Headers.Add(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Cookie&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;&lt;strong&gt;设置为你自己的COOKIE&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wc.DownloadFile(&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.Format(urlTemp,&amp;nbsp;beginId&amp;nbsp;+&amp;nbsp;i),&amp;nbsp;(beginId&amp;nbsp;+&amp;nbsp;i).ToString());&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;span  style="font-family: 'Courier New'; line-height: 22px; background-color: #f5f5f5; "&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;第三步 分析已抓取文件中的数据&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;用到了简单的正则表达式。本例中所处理的对象为JSON，我们采用Newtonsoft.JSON进行处理。将分析结果保存到Dictionary&amp;lt;string,int&amp;gt;数据结构中，同时更新统计的总场次。&lt;/p&gt; &lt;p&gt;&lt;span  style="font-family: 'Courier New'; line-height: 22px; background-color: #f5f5f5; "&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;读取之前所抓的文件内容&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param&amp;nbsp;name="l"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&amp;nbsp;ReadFiles(&lt;span style="color: #0000FF;"&gt;long&lt;/span&gt;&amp;nbsp;l)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&amp;nbsp;sr&amp;nbsp;=&amp;nbsp;File.OpenText(l.ToString());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&amp;nbsp;content&amp;nbsp;=&amp;nbsp;sr.ReadToEnd();&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;正则表达式提取出HTML文件中的JSON&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&amp;nbsp;m&amp;nbsp;=&amp;nbsp;Regex.Matches(content,&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;HeroList.*]&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;RegexOptions.Compiled);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(m.Count&amp;nbsp;&amp;gt;&amp;nbsp;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;将JSON变成Record类&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&amp;nbsp;list&amp;nbsp;=&amp;nbsp;JsonConvert.DeserializeObject&amp;lt;List&amp;lt;Record&amp;gt;&amp;gt;(m[&lt;span style="color: #800080;"&gt;0&lt;/span&gt;].ToString().Replace(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;HeroList&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #800000;"&gt;""&lt;/span&gt;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&amp;nbsp;item&amp;nbsp;&lt;span style="color: #0000FF;"&gt;in&lt;/span&gt;&amp;nbsp;list)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(!dicMvp.ContainsKey(item.heroname))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dicMvp.Add(item.heroname,&amp;nbsp;item.mvp);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dicMvp[item.heroname]&amp;nbsp;=&amp;nbsp;dicMvp[item.heroname]&amp;nbsp;+&amp;nbsp;item.mvp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;累计场次&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BattleCount&amp;nbsp;+=&amp;nbsp;item.lost&amp;nbsp;+&amp;nbsp;item.win&amp;nbsp;+&amp;nbsp;item.offline;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;第四步 制作直观的统计结果&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;软件的用户怎么查看程序运营的结果呢？一般无外乎就是文本文件、网页、图片。我们先写个简单的文本文件吧！。（如果写个漂亮的HTML5页面，相信效果会非常好哦）注意在输出结果前，先把Dictionary&amp;lt;string,int&amp;gt;排序一下，可以使用到简单的lambda表达式。&lt;/p&gt; &lt;p&gt;&lt;span  style="font-family: 'Courier New'; line-height: 22px; background-color: #f5f5f5; "&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;分析结果&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&amp;nbsp;GetResult()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&amp;nbsp;sw&amp;nbsp;=&amp;nbsp;File.CreateText(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;result.txt&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StringBuilder&amp;nbsp;sb&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;StringBuilder();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&amp;nbsp;item&amp;nbsp;&lt;span style="color: #0000FF;"&gt;in&lt;/span&gt;&amp;nbsp;dicMvp.OrderByDescending(p&amp;nbsp;=&amp;gt;&amp;nbsp;p.Value))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sb.AppendFormat(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;{0}:{1}\n&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;item.Key,&amp;nbsp;item.Value);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Write(sb.ToString());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Write(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;\n\n总统计场次:&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&amp;nbsp;+&amp;nbsp;BattleCount);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sw.Close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;运算结果是这样的：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/201112/201112311248464260.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/201112/201112311248577891.png" width="804" height="477" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;在&lt;strong&gt;已统计的数十万场比赛中，最容易获得MVP的英雄前十名依次为：神灵武士、屠夫、嗜血狂魔、赏金猎人、幽鬼、影魔、山岭巨人、召唤师、敌法师、先知。&lt;/strong&gt; 当然，如果统计范围再大一点（把抓取数据的程序跑一整天即可），涉及场次达到千万级，结果会更加准确。&lt;/p&gt; &lt;p&gt;怎么样，非常简单吧？嘿嘿，之前说过了，本文只做抛砖引玉，为那些初学.NET找不到练手项目的人增加一些思路。您可以根据本文很轻松地制作出&amp;#8220;最容易打钱的英雄&amp;#8221;&amp;#8220;杀人数最多的英雄&amp;#8221;&amp;#8220;最容易推塔的英雄&amp;#8221;&amp;#8220;最坑爹的英雄&amp;#8221;等等等等。。。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;关于Dota辅助程序&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;其实，当您熟知了本文所提及的这些&amp;#8220;基础知识&amp;#8221;以后，您会发现11对战平台的统计数据可以做非常多的事。&lt;/p&gt; &lt;p&gt;关于Dota辅助程序是我一位同事提出的，可以是各种对战平台（不限于11）的插件形式。可以做的事情有：&lt;/p&gt; &lt;p&gt;1.根据海量统计数据，在某场Dota比赛开始后，根据场上10个英雄，告诉玩家哪个英雄最容易获得MVP。&lt;/p&gt; &lt;p&gt;2.根据海量统计数据和场上已选的9个英雄，告诉玩家应该选哪个英雄更容易打出好的成绩。&lt;/p&gt; &lt;p&gt;3.根据海量统计数据告诉玩家此局应该怎么出装备、怎么升级能甚至整体策略。&lt;/p&gt;  &lt;p&gt;4.根据海量统计数据（尤其是天梯的数据），告诉玩家在CM模式（或其他组队模式）应该怎么选英雄搭配（还可以结合对方选的英雄实时运算新策略）。&lt;/p&gt; &lt;p&gt;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&lt;/p&gt; &lt;p&gt;砖已经够多了，玉就靠你们了。 o(&amp;#8745;_&amp;#8745;)o&lt;/p&gt; &lt;p&gt;有任何问题，欢迎咨询，&lt;a href="http://weibo.com/cloudera" target="_blank"&gt;刘小排r&lt;/a&gt;（新浪微博&lt;a href="http://weibo.com/cloudera"&gt;http://weibo.com/cloudera&lt;/a&gt;)知无不言，言无不尽。&lt;/p&gt;&lt;p&gt;文中原代码下载地址http://files.cnblogs.com/azure/11Stat.rar&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/azure/aggbug/2308628.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/azure/archive/2011/12/31/Dota_MVP.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/azure/archive/2011/11/30/Social_Recommendation.html</id><title type="text">来，再做一个社会化推荐引擎</title><summary type="text">三年前,一位叫郑昀的高手发布社会化推荐产品“玩聚SR”。我们并不是在探讨如何简单地复制郑昀以前的工作，而是探讨如何站在巨人的肩膀上，把社会化推荐引擎做得更好、更全面、更讨用户喜欢(预览地址http://dullcat.com)。</summary><published>2011-11-29T18:01:00Z</published><updated>2011-11-29T18:01:00Z</updated><author><name>流牛木马</name><uri>http://www.cnblogs.com/azure/</uri></author><link rel="alternate" href="http://www.cnblogs.com/azure/archive/2011/11/30/Social_Recommendation.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/azure/archive/2011/11/30/Social_Recommendation.html"/><content type="html">&lt;p&gt;&lt;strong&gt;A.背景&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在阅读本文之前，我们强烈建议您阅读一下&lt;a href="http://zhengyun.wealink.com/"&gt;郑昀&lt;/a&gt; 的《&lt;a href="http://www.cnblogs.com/zhengyun_ustc/archive/2008/12/22/ju690_sr.html"&gt;来，做一个社会化推荐引擎&lt;/a&gt;》和《&lt;a href="http://www.cnblogs.com/zhengyun_ustc/archive/2011/02/05/aboutidea.html"&gt;一个想法从构思到实现只需7天&lt;/a&gt;》，本文所讨论的议题以及我们正在做的事情，都始于他以前在相同领域的工作与思考。我们的测试版社会化推荐引擎取名为&amp;#8220;&lt;a href="http://dullcat.com/" target="_blank"&gt;玩聚猫&lt;/a&gt;&amp;#8221;(&lt;a href="http://dullcat.com/"&gt;http://dullcat.com&lt;/a&gt;) ，也是在名称上延续&lt;a href="http://zhengyun.wealink.com/"&gt;郑昀&lt;/a&gt;在三年前发布的同类产品&amp;#8220;玩聚SR&amp;#8221;。&lt;/p&gt; &lt;p&gt;当然，我们并不是在探讨如何简单地复制&lt;a href="http://zhengyun.wealink.com/"&gt;郑昀&lt;/a&gt;以前的工作，而是探讨如何站在巨人的肩膀上，把社会化推荐引擎做得更好、更全面、更讨用户喜欢。&lt;/p&gt;&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/azure/wjm.jpg" width="1149" height="651" alt="玩聚猫" /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;strong&gt;B.什么是&lt;a href="http://dullcat.com/" target="_blank"&gt;社会化推荐（Social Recommendation,SR）&lt;/a&gt;?&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://zhengyun.wealink.com/"&gt;郑昀&lt;/a&gt;在三年前对此的定义是&amp;#8220;&lt;em&gt;选择一批IT业界人士的社会化媒体分享源，如&lt;/em&gt;&lt;em&gt;曹增辉&lt;/em&gt;&lt;em&gt;、&lt;/em&gt;&lt;em&gt;冯大辉&lt;/em&gt;&lt;em&gt;的GoogleReader分享，&lt;/em&gt;&lt;em&gt;白鸦&lt;/em&gt;&lt;em&gt;、&lt;/em&gt;&lt;em&gt;困兽&lt;/em&gt;&lt;em&gt;的&lt;/em&gt;&lt;em&gt;twitter&lt;/em&gt;&lt;em&gt;，&lt;/em&gt;&lt;em&gt;张亮&lt;/em&gt;&lt;em&gt;的&lt;/em&gt;&lt;em&gt;饭否&lt;/em&gt;&lt;em&gt;，还有&lt;/em&gt;&lt;em&gt;叽歪de&lt;/em&gt;&lt;em&gt;、&lt;/em&gt;&lt;em&gt;delicious&lt;/em&gt;&lt;em&gt;等等。对这些信息源的分享链接进行汇总，一个信息源推荐就算一票，综合票数、信息源权重、推荐时间点、信息源类型等多种因素，最终形成像&lt;/em&gt;&lt;em&gt;鲜果热文&lt;/em&gt;&lt;em&gt;、&lt;/em&gt;&lt;em&gt;digg&lt;/em&gt;&lt;em&gt;或&lt;/em&gt;&lt;em&gt;Reddit&lt;/em&gt;&lt;em&gt;一样的跨平台社会化推荐引擎，并进一步引入语义关联技术，进化到&lt;/em&gt;&lt;em&gt;协同过滤&lt;/em&gt;&lt;em&gt;+语义过滤的自动化系统。&amp;#8221;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;由于数据源的原因，&lt;a href="http://zhengyun.wealink.com/"&gt;郑昀&lt;/a&gt;的定义比较强调&amp;#8220;IT业界人士&amp;#8221;，而我们想淡化这一点。&lt;/p&gt; &lt;p&gt;我们认为，&lt;a href="http://dullcat.com/" target="_blank"&gt;社会化推荐&lt;/a&gt;系统是从社会化媒体中，根据一系列的算法，发现热门内容的系统。其使用的算法除了常规的数据挖掘、聚类外，主要是对各种信息源的『分享行为』进行汇总，对『分享行为』进行加权，综合『分享行为』的数量、信息源权重、推荐时间点、信息源类型等多种因素。她能分享最有价值的信息，能具有视野发散度，能削减信息爆炸。&lt;/p&gt; &lt;p&gt;『分享行为』是指用户在社会化媒体中对特定内容进行分享的行为，包括但不限于新浪微博的&amp;#8220;转发&amp;#8221;、人人网的&amp;#8220;喜欢&amp;#8221;、Google Plus的&amp;#8220;+1&amp;#8221;、以及Digg类网站的&amp;#8220;顶&amp;#8221;等等。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;C.我们为什么要重复发明车轮？&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;原因很简单的，诞生于三年前的&lt;a href="http://zhengyun.wealink.com/"&gt;郑昀&lt;/a&gt;版社会化推荐系统有他的局限性：&lt;/p&gt; &lt;p&gt;a)由于过分依赖于IT业界人士,所推荐的内容难以吸引非IT人士&lt;/p&gt; &lt;p&gt;b)数据源较少（无论是种类还是数量），Google Reader Shared Item和Twitter占据了超过85%的信息。&lt;/p&gt; &lt;p&gt;c)由于b)，没有形成在更大范围通用的排名公式。&lt;/p&gt; &lt;p&gt;d)没有像Google PR( Google PageRank)那样的指标，无法向用户直观地体现特定文章的价值。&lt;/p&gt; &lt;p&gt;e)推荐者权重模型（如名人效应）没有得到体现&lt;/p&gt; &lt;p&gt;因此，我们打算重新发明车轮，进行一场新的社会化推荐革命！&lt;/p&gt; &lt;p&gt;&lt;strong&gt;D.玩聚猫社会化推荐的数据源应该包含哪些？&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;我们把国内社会化分享媒体分为以下四类：&lt;/p&gt; &lt;p&gt;a) 微博、轻博客类。包含腾讯微博、新浪微博、网易微博、点点网、新浪Qing等；&lt;/p&gt; &lt;p&gt;b) SNS类。包含人人网、开心网、腾讯朋友等；&lt;/p&gt; &lt;p&gt;c) 书签、网摘类。包含强国网摘、CSDN网摘系统、爱库网、QQ书签、有道书签、百度搜藏等等；&lt;/p&gt; &lt;p&gt;d)RSS阅读器。包含Google Reader、鲜果、抓虾、豆瓣9点等等。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;E.玩聚猫在处理不同类型社会化分享媒体的『分享行为』要考虑哪些因素？&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;上文也零星提及了一些，归纳起来有以下几点重要差异：&lt;/p&gt; &lt;p&gt;a)&amp;nbsp; 『分享行为』类型不同。新浪微博有&amp;#8220;转发&amp;#8221;、人人网有&amp;#8220;喜欢&amp;#8221;、豆瓣9点有&amp;#8220;推荐&amp;#8221;、有的网站只有&amp;#8220;阅读量&amp;#8221;。&lt;/p&gt; &lt;p&gt;b)&amp;nbsp; 网站权重不同。例如爱库网上最热的内容，权重肯定没有新浪微博上同一时间最热的内容权重高。&lt;/p&gt; &lt;p&gt;c)『分享行为』发起人的权重不同。例如李开复转发了一条微博，权重会比50个我转发同样一条微博更高。&lt;/p&gt; &lt;p&gt;d) 『分享行为』的时间也会影响权重。很多时候对于同一信息源、同一内容的『分享行为』是呈指数衰减的。例如在郭美美事件，我第一次在新浪微博看到时已经拥有了两万次转发，我看完后决定转发第两万零一次，明显我的这次转发的权重比第两千零一次转发的权重小。&lt;/p&gt; &lt;p&gt;e)&amp;nbsp; 考虑去重复。例如我同时在我新浪微博和腾讯微博转发了同样一条微博，只能计数一次。&lt;/p&gt; &lt;p&gt;当然，我们希望这些差异对用户透明，因为用户不需要了解这么多。用户只需要一个类似Google PR的数字直接了当地告诉他文章价值就可以了。&lt;/p&gt; &lt;p&gt;所以我们引入了&lt;strong&gt;SR&lt;/strong&gt;(Social Rank)，范围0～10，标识在每篇文章的标题后面。一篇文章的SR能够精确表示它在其他各种社会化媒体的火热程度。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;F.玩聚猫SR的计算公式&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;设置我们有N种数据源，分别是 &lt;font size="3"&gt;{S&lt;/font&gt;&lt;font size="1"&gt;1&lt;/font&gt;&lt;font size="3"&gt;,S&lt;/font&gt;&lt;font size="1"&gt;2&lt;/font&gt;,&lt;font size="3"&gt;S&lt;/font&gt;&lt;font size="1"&gt;3&lt;/font&gt;&amp;#8230;.&lt;font size="3"&gt;S&lt;/font&gt;&lt;font size="1"&gt;n&lt;/font&gt;&lt;font size="3"&gt;} &amp;#8712; S &lt;/font&gt;&lt;/p&gt; &lt;p&gt;如前文所述，数据源有4种类型，分别是&lt;font size="3"&gt;{&lt;/font&gt;&lt;font size="3"&gt;T&lt;/font&gt;1,&lt;font size="3"&gt;T&lt;/font&gt;2,&lt;font size="3"&gt;T&lt;/font&gt;3,&lt;font size="2"&gt;T&lt;/font&gt;4&lt;font size="3"&gt;}&lt;/font&gt;&lt;font size="3"&gt;&amp;#8712; T&lt;/font&gt;。&lt;/p&gt; &lt;p&gt;设类型权重 &lt;font size="3"&gt;{W&lt;/font&gt;&lt;font size="3"&gt;T&lt;/font&gt;1,&lt;font size="3"&gt;WT&lt;/font&gt;2,&lt;font size="3"&gt;WT&lt;/font&gt;3,&lt;font size="3"&gt;WT&lt;/font&gt;4&lt;font size="3"&gt;}&amp;#8712;W T&lt;/font&gt;&lt;/p&gt; &lt;p&gt;对于数据源&lt;font size="3"&gt;S&lt;/font&gt;i , &lt;/p&gt; &lt;p&gt;设数据源自身权重为&lt;font size="3"&gt;SW&lt;/font&gt;(i),&lt;font size="3"&gt; SW&lt;/font&gt;(i)由网站的Alexa排名、PV量、修正值决定。&lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;T&lt;/font&gt;(i)表示它所属于的分类，&lt;font size="3"&gt;WT&lt;font size="2"&gt;(&lt;/font&gt;T&lt;/font&gt;(i&lt;font size="2"&gt;) )&amp;nbsp; 表示Si的类型权重&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;在计算某篇文章的SR时，设&lt;font size="3"&gt;A&lt;/font&gt;(i) 是该文章在Si数据源里的『分享行为』计数。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;那么，&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;对于这篇文章而言，&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;font size="2"&gt;SR = &lt;font size="3"&gt;Log&lt;/font&gt;&lt;/font&gt;&lt;font size="1"&gt;x&amp;nbsp; &lt;/font&gt;&lt;font size="3"&gt;&amp;#8721;&lt;/font&gt;&lt;font size="1"&gt;i=1..n&lt;/font&gt;&lt;font size="3"&gt;A&lt;/font&gt;(i) &lt;font size="3"&gt;&amp;#215;WT(T&lt;/font&gt;(i&lt;font size="2"&gt;) )&lt;font size="3"&gt;&amp;#215;&lt;/font&gt; &lt;font size="3"&gt;SW&lt;/font&gt;(i)&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;为什么是&lt;font size="2"&gt;&lt;font size="3"&gt;Log&lt;/font&gt;&lt;/font&gt;&lt;font size="1"&gt;x &lt;/font&gt;&lt;/font&gt;呢？ 有两点原因，一是它可以使得早期的投票获得更大的权重，比如，当x=10时，前 10 票获得的权重，与 11 到 101 票所获得的权重是一样的；二是使信息的层级呈金字塔型分布，就像Google PR、地震里氏等级一样。&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&lt;font size="3"&gt;Log&lt;/font&gt;&lt;/font&gt;&lt;font size="1"&gt;x &lt;/font&gt;中&lt;font size="3"&gt;x&lt;/font&gt;的取值非常重要，玩聚猫的取法是这样的：从已知的m篇预料信息中计算最大的推荐价值&lt;/p&gt; &lt;p&gt;&lt;font color="#0000ff"&gt;MaxV= Max( &lt;font size="3"&gt;V&lt;/font&gt;&lt;font size="1"&gt;j&lt;/font&gt;= &lt;font size="3"&gt;&amp;#8721;&lt;/font&gt;&lt;font size="1"&gt;i=1..n&lt;/font&gt;&lt;font size="3"&gt;A&lt;/font&gt;(i) &lt;font size="3"&gt;&amp;#215;WT(T&lt;/font&gt;(i&lt;font size="2"&gt;) )&lt;font size="3"&gt;&amp;#215;&lt;/font&gt; &lt;font size="3"&gt;SW&lt;/font&gt;(i) |&lt;font size="1"&gt; j=1..m&lt;/font&gt;&amp;nbsp; )&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;由于SR的范围是0至10，我们令 &lt;font size="3"&gt;x&lt;/font&gt;^10 =MaxV &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;从而计算出 &lt;/font&gt;&lt;font color="#0000ff" size="3"&gt;x =&amp;nbsp; 10&amp;#8730;MaxV&lt;/font&gt;&lt;/p&gt; &lt;p&gt;如果MaxV为35000，则X应该设定为2.847，&lt;font color="#333333"&gt;&lt;font size="2"&gt;SR = &lt;font size="3"&gt;Log&lt;/font&gt;&lt;/font&gt;&lt;font size="1"&gt;2.847 &lt;/font&gt;&lt;font size="3"&gt;&amp;#8721;&lt;/font&gt;&lt;font size="1"&gt;i=1..n&lt;/font&gt;&lt;font size="3"&gt;A&lt;/font&gt;(i) &lt;font size="3"&gt;&amp;#215;WT(T&lt;/font&gt;(i&lt;font size="2"&gt;) )&lt;font size="3"&gt;&amp;#215;&lt;/font&gt; &lt;font size="3"&gt;SW&lt;/font&gt;(i)；推荐价值约200的文章SR为5，推荐价值约4500的文章SR为8，推荐价值大于35000的文章SR为10&lt;/font&gt;。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;通过这样的公式，为每篇文章都计算出一个Rank值，用户就能直观又精确地了解到文章的价值了。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;&amp;#215;注意：玩聚猫的SocialRank和《&lt;a href="http://www.cnblogs.com/zhengyun_ustc/archive/2008/12/22/ju690_sr.html" target="_blank"&gt;来，做一个社会化推荐引擎&lt;/a&gt;&lt;/font&gt;》里提到的排序依据SR Rank不同。玩聚猫的SR跟列表排序依据没关系，只跟内容本身的价值有关系；&lt;a href="http://zhengyun.wealink.com/"&gt;郑昀&lt;/a&gt; 只跟排序有关系。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;G.玩聚猫还有哪些需要改进的地方？&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;我们正在以下领域进行奋斗：&lt;br /&gt;1.强化用户权重系统，尤其是引入模糊计算和估值，强调名人效应。&lt;br /&gt;2.通过实验数据，不断改进排名算法。&lt;br /&gt;3.引入智能语义、自然语言，使玩聚猫在面对文本信息时，能够以人类而非机械的方式进行思考、归类、关联、过滤、总结。&lt;br /&gt;4.引入机器学习(如Prediction)，使玩聚猫能够记住每一个用户的口味，个性化地推荐文章。 &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;如果你对社会化推荐感兴趣的话，不妨到&lt;a href="http://dullcat.com/"&gt;玩聚猫&lt;/a&gt;&lt;font color="#000000"&gt;&lt;/font&gt;看看（目前是测试版本，服务器在国外，可能不太稳定，请见谅）。我们热忱欢迎您的一切宝贵意见、建议和批评。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/azure/aggbug/2268502.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/azure/archive/2011/11/30/Social_Recommendation.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/azure/archive/2010/09/29/1837991.html</id><title type="text">11个IT人士必备的Chrome 插件</title><summary type="text">Chrome 浏览器现在可谓如日中天，与 Firefox 共同蚕食着 IE 的市场，网页开发者们可能也会开始转向这一新兴的浏览器，来调校自己的网站。而随着 Chrome 插件作者们的介入，为网页开发者提供便利的插件也纷纷崭露头角。1.Firebug LiteFirebug 绝对是最受网页开发者喜爱的 Fifefox 插件（没有之一）。通过它可以在浏览器中查看并编辑任何网页的 HTML，CSS 以及...</summary><published>2010-09-28T16:21:00Z</published><updated>2010-09-28T16:21:00Z</updated><author><name>流牛木马</name><uri>http://www.cnblogs.com/azure/</uri></author><link rel="alternate" href="http://www.cnblogs.com/azure/archive/2010/09/29/1837991.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/azure/archive/2010/09/29/1837991.html"/><content type="html">&lt;span  style="font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; line-height: 22px; font-size: 15px; "&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;Chrome 浏览器现在可谓如日中天，与 Firefox 共同蚕食着 IE 的市场，网页开发者们可能也会开始转向这一新兴的浏览器，来调校自己的网站。而随着 Chrome 插件作者们的介入，为网页开发者提供便利的插件也纷纷崭露头角。&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;1.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/bnbbfjbeaefgipfjpdabmpadaacmafkj" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;Firebug Lite&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/firebuglite.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="firebuglite" border="0" alt="firebuglite" src="http://lucifr.com/wp-content/uploads/2010/02/firebuglite_thumb.jpg" width="640" height="226" original="http://lucifr.com/wp-content/uploads/2010/02/firebuglite_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;Firebug 绝对是最受网页开发者喜爱的 Fifefox 插件（没有之一）。通过它可以在浏览器中查看并编辑任何网页的 HTML，CSS 以及 JavaScript，并在修改的同时地看到改动后的效果。Firebug Lite 是针对 Chrome 浏览器的一个精简版本，可以用来查找网页中的错误以便快速更正。&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;尽管 Firebug Lite 尚不能包括 Firebug 所有功能，但也已经秉承其精粹，且已经提供了针对高级用户控制台界面。&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;2.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/hehijbfgiekmjfkfjpbkbammjbdenadd" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;IE Tab&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/ietab.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="ietab" border="0" alt="ietab" src="http://lucifr.com/wp-content/uploads/2010/02/ietab_thumb.jpg" width="640" height="129" original="http://lucifr.com/wp-content/uploads/2010/02/ietab_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;微软的 Internet Explorer 浏览器会让很多网页设计者头痛，但目前为止在大众范围内仍是被使用最多的浏览器。IE Tab 扩展实际上是在 Chrome 的一个标签页里用 IE 打开网页，通过它你可以查看网页在 IE 用户的眼里是否显示正常。&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;3.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/hmdcmlfkchdmnmnmheododdhjedfccka" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;Eye Dropper&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/eyedropper.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="eyedropper" border="0" alt="eyedropper" src="http://lucifr.com/wp-content/uploads/2010/02/eyedropper_thumb.jpg" width="640" height="335" original="http://lucifr.com/wp-content/uploads/2010/02/eyedropper_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;通过 EyeDropper，可以查看 Chrome 浏览的网页中任意颜色的信息。点击扩展的按钮，会打开一个下拉式的色轮界面，其中有一个取色器按钮（Pick color from webpage），点击它，再点击网页中任何位置，就可以查看所点击位置像素的颜色在色轮中的位置、RGB 水平以及 HTML 颜色代码。&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;4.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/oangcciaeihlfmhppegpdceadpfaoclj" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;Chrome SEO&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/measureit.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="measureit" border="0" alt="measureit" src="http://lucifr.com/wp-content/uploads/2010/02/measureit_thumb.jpg" width="640" height="234" original="http://lucifr.com/wp-content/uploads/2010/02/measureit_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;安装好该插件后点击插件按钮就会显示当前网站与搜索引擎优化相关的信息，包括反向链接，Alexa排名、Google PageRank排名等流量值数，在社会化书签网站中的热门程度等。&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;5.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/dmpfoncmmihgkooacnplecaopcefceam" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;Lorem Ipsum Generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/loremipsum.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="loremipsum" border="0" alt="loremipsum" src="http://lucifr.com/wp-content/uploads/2010/02/loremipsum_thumb.jpg" width="640" height="210" original="http://lucifr.com/wp-content/uploads/2010/02/loremipsum_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;Lorem Ipsum Generator 扩展可以用来在设计网页时生成填充网页内容的文本，用以调适格式，免去手动输入此类文字浪费的时间。该插件十分小巧，在易于使用的同时也不会占用过多的内存，在需要时可以信手拈来。&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;6.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/idhfcdbheobinplaamokffboaccidbal" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;Resolution Test&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/resolutiontest.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="resolutiontest" border="0" alt="resolutiontest" src="http://lucifr.com/wp-content/uploads/2010/02/resolutiontest_thumb.jpg" width="640" height="345" original="http://lucifr.com/wp-content/uploads/2010/02/resolutiontest_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;顾名思义，Resolution Test 就是通过调整浏览器的大小来查看网站在不同的常见分辨率下的情况。作为网页设计者一般都会配备高分辨率的显示器，但一般的网页访问者来说通常都不会这么奢侈，这个扩展的作用就是用来确保网站的格式在这部分人看来也是正常的。&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;7.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/ognampngfcbddbfemdapefohjiobgbdl" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;Speed Tracer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/speedtracer.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="speedtracer" border="0" alt="speedtracer" src="http://lucifr.com/wp-content/uploads/2010/02/speedtracer_thumb.jpg" width="640" height="156" original="http://lucifr.com/wp-content/uploads/2010/02/speedtracer_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;Speed Tracer 通过浏览器内建的测量工具来记录网页应用在执行不同任务时所用的时间，以便于开发者找到致使网站运行缓慢的原因。该插件可以显示浏览器在解读执行布局、Javascript时所有的时间以及其它一些细节。&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;这个插件唯一的缺点在于，必须使用&amp;#8220;&amp;#8211;enable-extension-timeline-api&amp;#8221;这个参数来启动 Chrome 浏览器才能让其正常运作。但既然是网站开发者，这点麻烦就是小菜一碟了，对吧？&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;8.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/aonjhmdcgbgikgjapjckfkefpphjpgma" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;MeasureIt!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/measureit1.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="measureit" border="0" alt="measureit" src="http://lucifr.com/wp-content/uploads/2010/02/measureit_thumb1.jpg" width="640" height="234" original="http://lucifr.com/wp-content/uploads/2010/02/measureit_thumb1.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;MeasureIt! 名字就很直观。它可以显示出所浏览网页中任意元素的尺寸（像素宽度和高度）。和这个列表中很多插件一样，这个插件也有 Firefox 版本。&lt;/p&gt;&lt;p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;9.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/aonjhmdcgbgikgjapjckfkefpphjpgma" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;1-Click&lt;/a&gt;&amp;nbsp;Web Proxy&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span  style="font-size: 17.28px; "&gt;&lt;img src="https://chrome.google.com/extensions/img/kjdehhkgdgjcekacdccoflccmhbkefce/1285559244.86/screenshot/7001" border="0"  alt="" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span  style="font-size: 17.28px; "&gt;&lt;img src="https://chrome.google.com/extensions/img/kjdehhkgdgjcekacdccoflccmhbkefce/1285559244.86/screenshot/5001" border="0"  alt="" /&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;地址:&amp;nbsp;&lt;span  style="font-size: 17.28px; "&gt;&lt;a href="https://chrome.google.com/extensions/detail/kjdehhkgdgjcekacdccoflccmhbkefce"&gt;https://chrome.google.com/extensions/detail/kjdehhkgdgjcekacdccoflccmhbkefce&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;这个插件应该是国人做的。因为她的中文名字是&amp;#8212;&amp;#8212; &amp;nbsp;一键翻墙！&lt;/p&gt;&lt;p&gt;她已经连续一个月排到Chrome Extension 官方Top Rated的第7名了～ 囧～ 看来还真是迎合国民的需求啊～&lt;/p&gt;&lt;p&gt;真相在这里：&lt;span  style="font-size: 17.28px; "&gt;&lt;a href="https://chrome.google.com/extensions/list/rating"&gt;https://chrome.google.com/extensions/list/rating&lt;/a&gt;&lt;/span&gt;&lt;span  style="font-size: 17.28px; "&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;做IT的经常去国外网站查资料，遇到打不开的网页，比如google groups 、blogspot等，只需要点击这个插件的按钮就可以了。速度还挺不错。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;10.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/gbkffbkamcejhkcaocmkdeiiccpmjfdi" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;Pendule&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/pendule.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="pendule" border="0" alt="pendule" src="http://lucifr.com/wp-content/uploads/2010/02/pendule_thumb.jpg" width="640" height="220" original="http://lucifr.com/wp-content/uploads/2010/02/pendule_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;Pendule 会弹出一个简单易用且设计精美的控制面板，其中包含了很多对于开发者来说很有帮助的任务选项。比如重新载入或是禁用 CSS，查看 JavaScript 代码，隐藏图片，取色器，测量尺，查看页面源代码，以及多种编码验证工具等。是一个很不错的功能基础且全面的开发者用扩展。&lt;/p&gt;&lt;h4 style="padding-top: 0.2em; padding-right: 0px; padding-bottom: 0.2em; padding-left: 0.5em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-weight: bold; font-size: 15px; color: #333333; border-left-width: 0.5em; border-left-style: solid; border-left-color: #0c87c0; text-shadow: #cccccc 1px 1px 1px; "&gt;11.&amp;nbsp;&lt;a href="https://chrome.google.com/extensions/detail/dapjbgnjinbpoindlpdmhochffioedbn" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: none; color: #333333 !important; "&gt;BuiltWith&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;&lt;a href="http://lucifr.com/wp-content/uploads/2010/02/builtwith.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-decoration: underline; color: #0c87c0; "&gt;&lt;img title="builtwith" border="0" alt="builtwith" src="http://lucifr.com/wp-content/uploads/2010/02/builtwith_thumb.jpg" width="640" height="391" original="http://lucifr.com/wp-content/uploads/2010/02/builtwith_thumb.jpg" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; max-width: 100%; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; display: inline; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 1.467em; margin-left: 0px; "&gt;BuiltWith 可以给出关于当前网页的一个资料信息，列出了网站中所使用的相关技术。它会显示网页中所使用的小挂件、网站管理员所用的网站流量分析追踪服务、网页所使用的框架以及广告平台等等。&lt;/p&gt;&lt;/span&gt;&lt;img src="http://www.cnblogs.com/azure/aggbug/1837991.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/azure/archive/2010/09/29/1837991.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/azure/archive/2010/04/14/Chain_of_Responsibility_In_WorkflowPlatform.html</id><title type="text">使用职责链模式简化工作流相似步骤间的逻辑</title><summary type="text">    在实际建立工作流模型时，往往会有很多相似步骤。相似步骤间的逻辑，往往又会包括大量的if..else..判断。本问将讨论使用职责链模式简化工作流相似步骤间的逻辑的方法。</summary><published>2010-04-14T12:45:00Z</published><updated>2010-04-14T12:45:00Z</updated><author><name>流牛木马</name><uri>http://www.cnblogs.com/azure/</uri></author><link rel="alternate" href="http://www.cnblogs.com/azure/archive/2010/04/14/Chain_of_Responsibility_In_WorkflowPlatform.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/azure/archive/2010/04/14/Chain_of_Responsibility_In_WorkflowPlatform.html"/><content type="html">&lt;p&gt;在实际建立工作流模型时，往往会有很多相似步骤。相似步骤间的逻辑，往往又会包括大量的if..else..判断。&lt;/p&gt;&#xD;
&lt;p&gt;例如，我们先看一个简单的报销流程。它很可能会是这样的：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/image_2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/image_thumb.png" width="654" height="93" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;看似很简单的四个步骤。但客户会告诉我们： 部门经理应该分为两个步骤，因为有些部门设立了&amp;#8220;副经理&amp;#8221;职位，有些部门甚至&amp;#8220;经理&amp;#8221;职位空缺，只设&amp;#8220;副经理&amp;#8221;。换言之，&amp;#8220;经理&amp;#8221;与&amp;#8220;副经理&amp;#8221;至少有一个。&lt;/p&gt;&#xD;
&lt;p&gt;于是我们将流程图改为以下情况：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/image_4.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/image_thumb_1.png" width="654" height="215" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们发现，增加了一个步骤后，需要增加四条&amp;#8220;流程路径&amp;#8221;。例如，按照途中的说明，当流程以及流转到了&amp;#8220;部门副经理&amp;#8221;时，取得下一个步骤需要做一次&amp;#8220;if&amp;#8230;else&amp;#8230;&amp;#8221;。如果当前部门有&amp;#8220;部门经理&amp;#8221;，则下一步流转到&amp;#8220;部门经理&amp;#8221;步骤；如果当前部门没有&amp;#8220;部门经理&amp;#8221;，则直接流转到&amp;#8220;会计&amp;#8221;步骤。&lt;/p&gt;&#xD;
&lt;p&gt;这似乎能够满足客户的要求。但客户的组织机构往往非常复杂，他很可能在某一个时刻又告诉我们：我们共有两级部门，一共四个经理职位，均需要按照上述方式进行流转。&lt;/p&gt;&#xD;
&lt;p&gt;这是非常清晰明了的一个需求。于是我们又继续修改流程模型为：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/image_8.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/image_thumb_3.png" width="654" height="307" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;此时我们就陷入了困境。这新增的两个步骤，带来了更多的逻辑关系，且每个逻辑关系都更为复杂。&lt;/p&gt;&#xD;
&lt;p&gt;例如，假如当前流程以及流转到了&amp;#8220;二级部门副经理&amp;#8221;处，工作流平台取得下一步骤需要做的判断至少有：&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;如果该部门有&amp;#8220;二级部门经理&amp;#8221;,则流转到&amp;#8220;二级部门经理&amp;#8221;； &lt;/li&gt;&#xD;
     &lt;li&gt;如果该部门没有&amp;#8220;二级部门经理&amp;#8221;，但有&amp;#8220;一级部门副经理&amp;#8221;，则流转到&amp;#8220;一级部门副经理&amp;#8221;； &lt;/li&gt;&#xD;
     &lt;li&gt;如果该部门没有&amp;#8220;二级部门经理&amp;#8221;，也没有&amp;#8220;一级部门副经理&amp;#8221;，但有&amp;#8220;一级部门经理&amp;#8221;，则流转到&amp;#8220;一级部门经理&amp;#8221; &lt;/li&gt;&#xD;
     &lt;li&gt;如果该部门没有&amp;#8220;二级部门经理&amp;#8221;，也没有&amp;#8220;一级部门副经理&amp;#8221;，也没有&amp;#8220;一级部门经理&amp;#8221;，则流转到&amp;#8220;会计&amp;#8221;步骤&lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;p&gt;可以看到，仅仅&amp;#8220;二级部门副经理&amp;#8221;这一个步骤的&amp;#8220;选择下一步骤&amp;#8221;逻辑，就包含了4个&amp;#8220;if&amp;#8230;else&amp;#8230;&amp;#8221;判断，这是非常丑陋的。开发组往往兵强马壮，此种情况也可以通过大量的人工来保证。不过，可以预计的是，客户的多种流程（如报销、列账、冲销、预付等），都有类似的部门经理逻辑。大量的重复工作，无法保证不出错。&lt;/p&gt;&#xD;
&lt;p&gt;更为恐怖的是，假如客户有一天，变成了三个层级的部门组织架构了呢? 从&amp;#8220;三级部门副经理&amp;#8221;开始，一直往上，到&amp;#8220;会计&amp;#8221;步骤，那是不是仍然采用这样简单粗暴的方式？ 再按照这种方式来做的话，也许我们就直接崩溃了。&lt;/p&gt;&#xD;
&lt;p&gt;怎么办呢？ &lt;/p&gt;&#xD;
&lt;p&gt;其实，在GoF的23个设计模式中，就已经提到了一个经典的解决方案：&lt;strong&gt;职责链模式&lt;/strong&gt;。&lt;/p&gt;&#xD;
&lt;table style="border-bottom: gray 1px dashed; border-left: gray 1px dashed; border-top: gray 1px dashed; border-right: gray 1px dashed" border="0" cellspacing="0" cellpadding="2" width="764"&gt;&#xD;
     &lt;tbody&gt;&#xD;
         &lt;tr&gt;&#xD;
             &lt;td valign="top" width="762"&gt;&lt;font face="黑体"&gt;职责链（Chain of Responsibility）模式&lt;/font&gt;&lt;font face="黑体"&gt;&lt;br /&gt;&#xD;
             &amp;nbsp;&amp;nbsp;&amp;nbsp; 责任链模式是一种对象的行为模式【GOF95】。在责任链模式里，很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递，直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求，这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。&lt;/font&gt;&lt;/td&gt;&#xD;
         &lt;/tr&gt;&#xD;
     &lt;/tbody&gt;&#xD;
&lt;/table&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;职责链模式的UML图： &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/_OEZ3HQO2%7D~EI1E94FEE1DT_2.jpg" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="_OEZ3HQO2}~EI1E94FEE1DT" border="0" alt="_OEZ3HQO2}~EI1E94FEE1DT" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/_OEZ3HQO2%7D~EI1E94FEE1DT_thumb.jpg" width="454" height="272" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个UML图非常有意思。我们可以注意到，Handler角色自己聚合成自己。这有点类似于《数据结构》里描述的&amp;#8220;链式结构&amp;#8221;。 &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;抽象处理者(Handler)角色&lt;/strong&gt;：定义出一个处理请求的接口。如果需要，接口可以定义出一个方法，以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。&lt;br /&gt;&#xD;
&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;具体处理者(ConcreteHandler)角色&lt;/strong&gt;：具体处理者接到请求后，可以选择将请求处理掉，或者将请求传给下家。由于具体处理者持有对下家的引用，因此，如果需要，具体处理者可以访问下家。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们将这个设计模式运用到刚才所提到的实际环境中。&lt;/p&gt;&#xD;
&lt;p&gt;这时，我们的&amp;#8220;抽象处理者&amp;#8221;(Handler)是一个&lt;strong&gt;能够返回下一步步骤名称&lt;/strong&gt;的处理类。对于上面提到的&amp;#8220;二级部门&amp;#8221;的情况，我们将会有五个&amp;#8220;具体处理者&amp;#8221;(ConcreteHandler)：二级部门副经理、二级部门经理、一级部门副经理、一级部门经理、会计。 他们属于两个类别：&amp;#8220;经理类&amp;#8221;与&amp;#8220;会计类&amp;#8221;。&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#8220;会计类&amp;#8221;的处理无逻辑判断。即，当步骤选择器流入&amp;#8220;会计类&amp;#8221;时，直接返回&amp;#8220;会计类&amp;#8221;的步骤名。&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#8220;经理类&amp;#8221;就复杂一些，需要判断当前部门各个层级经理的有无、各个层级经理的是否已经审批。这两种判断可以抽象为两个数组参数的比较。我们设定两个数组参数byte[] candidates与byte[] approvers。第一个数组表示，候选步骤的有与无；第二个数字表示，在数据库记录中，所有步骤的当前审批状态.&lt;/p&gt;&#xD;
&lt;p&gt;例如，假如一个部门有&amp;#8220;二级部门副经理、二级部门经理、一级部门经理&amp;#8221;，没有&amp;#8220;一级部门副经理&amp;#8221;，即所有职位从小到大排列，第三大的职位空缺，其余职位齐全&amp;#8212;&amp;#8212;则byte[] candidates的值可以设为{1,1,0,1}。在流程刚刚开始时，所有步骤均未审批，byte[] approvers值为{0,0,0,0}；假如当前流程已经流转到&amp;#8220;二级部门副经理&amp;#8221;步骤，则byte[] approvers可以的值为{1,0,0,0}。&lt;/p&gt;&#xD;
&lt;p&gt;业务规则有了，参数有了，具体该如何处理呢？其实就是比较两个数组中相同index对应值的相等与否。&lt;/p&gt;&#xD;
&lt;p&gt;例如，假设当前 candidates为{1,1,0,1}，approvers为{1,0,0,0}。从数组索引0开始，依次往后，我们可以知道&amp;#8220;需要&amp;#8221;&amp;#8220;二级部门副经理&amp;#8221;审批，当前&amp;#8220;二级部门副经理&amp;#8221;已经审批；&amp;#8220;需要&amp;#8221;&amp;#8220;二级部门经理&amp;#8221;审批，当前&amp;#8220;二级部门经理&amp;#8221;还未审批。很明显，流程下一步应该流转到&amp;#8220;二级部门经理&amp;#8221;步骤。&lt;/p&gt;&#xD;
&lt;p&gt;以上的自然语言描述翻译为算法为：按照索引从小到大的顺序，依次比较candidates数组与approvers数组的元素值是否相等；如果相等，跳到下一个索引处继续比较；如果不等，则返回当前索引所对照的步骤名称。&lt;/p&gt;&#xD;
&lt;p&gt;按照我们设计好的&amp;#8220;职责链模式&amp;#8221;实现这个整体算法。即：每个&amp;#8220;经理&amp;#8221;处理者类，只判断属于自己索引的两数组元素，如果相等，则&amp;#8220;处理&amp;#8221;（返回步骤名）；如果不等，则移交下家进行后续判断。&lt;/p&gt;&#xD;
&lt;p&gt;首先构造处理者基类：&lt;/p&gt;&#xD;
&lt;a href="http://11011.net/software/vspaste" target="_blank"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('fcf06490-7510-4e94-b2ed-70548b78316e')"&gt;&lt;img style="display: none" id="code_img_opened_fcf06490-7510-4e94-b2ed-70548b78316e"  onclick="cnblogs_code_hide('fcf06490-7510-4e94-b2ed-70548b78316e',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_fcf06490-7510-4e94-b2ed-70548b78316e" &gt;&#xD;
&lt;div&gt;&lt;!--&lt;br/ /&gt;&#xD;
&lt;br/ /&gt;&#xD;
Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;&#xD;
http://www.CodeHighlighter.com/&lt;br/ /&gt;&#xD;
&lt;br/ /&gt;&#xD;
--&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;处理者基类&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt; Handler&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt; dutyId;&lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;处理者对应的数据键值&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt; stepName;&lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;处理者对应步骤的名称&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt;&lt;span style="color: #000000"&gt; Handler successor;&lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;后继处理者&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt; SetSuccessor(Handler successor)&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.successor &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; successor;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;处理任务的抽象方法，必须在每个子类进行Override&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt; HandleRequest(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] candidates, &lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] approvers);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;构造两个类型的处理者子类：经理子类，会计子类。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('e7efafce-e1d3-47fa-a1f9-a14907cc3922')"&gt;&lt;img style="display: none" id="code_img_opened_e7efafce-e1d3-47fa-a1f9-a14907cc3922"  onclick="cnblogs_code_hide('e7efafce-e1d3-47fa-a1f9-a14907cc3922',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_e7efafce-e1d3-47fa-a1f9-a14907cc3922" &gt;&#xD;
&lt;div&gt;&lt;!--&lt;br/ /&gt;&#xD;
&lt;br/ /&gt;&#xD;
Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;&#xD;
http://www.CodeHighlighter.com/&lt;br/ /&gt;&#xD;
&lt;br/ /&gt;&#xD;
--&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; 会计处理者&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt; Accounting : Handler&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;会计处理者需要赋予&amp;#8220;流程步骤名&amp;#8221;&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt; Accounting(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt; _stepName)&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stepName &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; _stepName;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;当职责链到达会计步骤时，直接进入会计步骤&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;override&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt; HandleRequest(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] candidates, &lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] approvers)&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt; stepName;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; 经理处理者&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt; Manager : Handler&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;经理处理者需要赋予&amp;#8220;流程步骤名&amp;#8221;与对应的&amp;#8220;数据键值&amp;#8221;&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt; Manager(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt; _dutyId, &lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt; _stepName)&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dutyId &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; _dutyId;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stepName &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; _stepName;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;override&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt; HandleRequest(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] candidates, &lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] approvers)&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;div&gt;&lt;span style="color: #008000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //如果两个值不相等，说明这个步骤还未处理过。立即返回该步骤的名称。&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (candidates[dutyId] !&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; approvers[dutyId])&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt; stepName;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (successor &lt;/span&gt;&lt;span style="color: #000000"&gt;!=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt; successor.HandleRequest(candidates, approvers);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;throw&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; ArgumentNullException(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;没有指定successor！&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;客户端：&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('1174f16d-59f7-42e8-9fa6-0d1e6a2b8bff')"&gt;&lt;img style="display: none" id="code_img_opened_1174f16d-59f7-42e8-9fa6-0d1e6a2b8bff"  onclick="cnblogs_code_hide('1174f16d-59f7-42e8-9fa6-0d1e6a2b8bff',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_1174f16d-59f7-42e8-9fa6-0d1e6a2b8bff" &gt;&#xD;
&lt;div&gt;&lt;!--&lt;br/ /&gt;&#xD;
&lt;br/ /&gt;&#xD;
Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;&#xD;
http://www.CodeHighlighter.com/&lt;br/ /&gt;&#xD;
&lt;br/ /&gt;&#xD;
--&gt;&lt;span style="color: #000000"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;客户端&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt; StepSelector&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;假设初始情况是：有二级部门副经理、有二级部门经理、&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;无一级部门副经理、有一级部门经理&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] candidates;&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;初始时，所有人均为审批&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] approvers;&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;传入工作流平台的任务Id，初始化当前状态&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StepSelector(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt; taskId)&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;#9671;到业务平台中取得所有的候选步骤&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; candidates &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; GetCandidates(taskId);&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;例如，初始情况可能是这样的：有二级部门副经理、有二级部门经理、&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;无一级部门副经理、有一级部门经理。&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;则设置如下：&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;candidates = new byte[] { 1, 1, 0, 1 };&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;#9671;到流程平台中取得当前已经完成的步骤&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; approvers &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; GetApprovers(taskId);&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;初始时，所有人均为审批&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;approvers = new byte[] { 0, 0, 0, 0 };&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;客户端主要方法： 传入整体数据、当前状态，取得下一步骤的名称&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt; GetNextStep(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] candidates, &lt;/span&gt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[] approvers)&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Manager LevelTwoViceManager &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; Manager(&lt;/span&gt;&lt;span style="color: #800080"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;二级部门副经理审批&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Manager LevelTwoManager &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; Manager(&lt;/span&gt;&lt;span style="color: #800080"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;二级部门经理审批&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Manager LevelOneViceManager &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; Manager(&lt;/span&gt;&lt;span style="color: #800080"&gt;2&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;二级部门经理审批&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Manager LevelOneManager &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; Manager(&lt;/span&gt;&lt;span style="color: #800080"&gt;3&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;二级部门经理审批&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Accounting accounting &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; Accounting(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;公司会计审核&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;);&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LevelTwoViceManager.SetSuccessor(LevelTwoManager);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LevelTwoManager.SetSuccessor(LevelOneViceManager);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LevelOneViceManager.SetSuccessor(LevelOneManager);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LevelOneManager.SetSuccessor(accounting);&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;从最低值为&amp;#8220;二级部门副经理&amp;#8221;开始处理请求&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&#xD;
&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt; LevelTwoViceManager.HandleRequest(candidates, approvers);&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;请注意&amp;#8220;客户端&amp;#8221;的代码，它完完全全地示例了职责链模式的调用方法。总体分为三步：1. 实例化处理者。2. 设置后继关系 3.从最前端的处理者开始处理。&lt;/p&gt;&#xD;
&lt;p&gt;值得一提的是，这样的结构是符合&amp;#8220;&lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle" target="_blank"&gt;开放封闭原则&lt;/a&gt;&amp;#8221;的（对修改封闭，对扩展开放）。也就是说，无论是需要两个部门经理来审批，还是四个部门经理来审批，甚至扩展到六个部门经理审批，都是不需要修改已有的业务逻辑代码，只需要在客户端中增加更多的处理者类实例、增加每个类的后继处理者、设置参数，就可以了。&lt;/p&gt;&#xD;
&lt;p style="display: none"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/ChainOfResponsibility_2.jpg" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ChainOfResponsibility" border="0" alt="ChainOfResponsibility" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/35223fdd527a_11791/ChainOfResponsibility_thumb.jpg" width="244" height="227" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;img src="http://www.cnblogs.com/azure/aggbug/1712136.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/azure/archive/2010/04/14/Chain_of_Responsibility_In_WorkflowPlatform.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/azure/archive/2010/03/24/1693365.html</id><title type="text">玩转双核CPU：左手画圆，右手画方</title><summary type="text">     两年前，微软亚洲研究院出版了《编程之美》一书,其中的第一章第一节“让CPU占用率曲线听你指挥”一文，可谓是在全国范围内掀起了一股玩转CPU占用率曲线热。今天流牛木马与各位看官讨论的是：双核CPU，左手画圆，右手画方。</summary><published>2010-03-23T16:50:00Z</published><updated>2010-03-23T16:50:00Z</updated><author><name>流牛木马</name><uri>http://www.cnblogs.com/azure/</uri></author><link rel="alternate" href="http://www.cnblogs.com/azure/archive/2010/03/24/1693365.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/azure/archive/2010/03/24/1693365.html"/><content type="html">&lt;p&gt;两年前，微软亚洲研究院出版了《&lt;a href="http://book.douban.com/subject/3004255/" target="_blank"&gt;编程之美&lt;/a&gt;》一书,其中的第一章第一节&amp;#8220;让CPU占用率曲线听你指挥&amp;#8221;一文，可谓是在全国范围内掀起了一股玩转CPU占用率曲线热。我本人甚至在坐公交的时候都在思考如何折腾CPU占用率曲线。&lt;/p&gt; &lt;p&gt;书中给出了这样一张让人耳目一新的图，吸引了万千IT少年：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/image_2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/image_thumb.png" width="269" height="304" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;也许您会觉得这还不够好玩。我也是。对了，今天流牛木马打算与各位看官讨论的，是以下这幅图的效果&amp;#8212;&amp;#8212;双核的CPU，左手画圆，右手画方！&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/image_4.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/image_thumb_1.png" width="328" height="354" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;该书出版的时候，我正在微软亚洲研究院创新工程组实习，该书的好几位作者都是我的好朋友，如李东、陈远等 &amp;#8212;&amp;#8212;于是我可以负责任地告诉大家，该书的所有实习生作者 ，当时他们使用的都是Intel P4 3.4Ghz单核CPU ！ o(&amp;#8745;_&amp;#8745;)o&lt;/p&gt; &lt;p&gt;今天突然想到了这里，就打算拿我的Thinkpad T60来试试。CPU是Genuine Intel(R) CPU T2400 @1.83Ghz ， 双核。&lt;/p&gt; &lt;p&gt;首先我将书中提供的C++代码翻译成了C# .翻译过程没任何技术难度，仅供各位看官了解个大概：&lt;/p&gt;&lt;pre &gt;&lt;span style="background: silver; color: blue"&gt;using &lt;/span&gt;&lt;span style="background: silver"&gt;System;&#xD;
&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;using &lt;/span&gt;&lt;span style="background: silver"&gt;System.Collections.Generic;&#xD;
&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;using &lt;/span&gt;&lt;span style="background: silver"&gt;System.Linq;&#xD;
&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;using &lt;/span&gt;&lt;span style="background: silver"&gt;System.Text;&#xD;
&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;namespace &lt;/span&gt;&lt;span style="background: silver"&gt;ConsoleApplication1&#xD;
{&#xD;
    &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;class &lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Program&#xD;
    &lt;/span&gt;&lt;span style="background: silver"&gt;{&#xD;
        &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;static void &lt;/span&gt;&lt;span style="background: silver"&gt;Main(&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;string&lt;/span&gt;&lt;span style="background: silver"&gt;[] args)&#xD;
        {&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;const double &lt;/span&gt;&lt;span style="background: silver"&gt;SPLIT = 0.01;&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;const int &lt;/span&gt;&lt;span style="background: silver"&gt;COUNT = 200;&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;const double &lt;/span&gt;&lt;span style="background: silver"&gt;PI = 3.14159265;&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;const int &lt;/span&gt;&lt;span style="background: silver"&gt;INTERVAL = 100;&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;double&lt;/span&gt;&lt;span style="background: silver"&gt;[] busySpan = &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;new double&lt;/span&gt;&lt;span style="background: silver"&gt;[COUNT];  &lt;/span&gt;&lt;span style="background: silver; color: green"&gt;//array of busy times&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;double&lt;/span&gt;&lt;span style="background: silver"&gt;[] idleSpan = &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;new double&lt;/span&gt;&lt;span style="background: silver"&gt;[COUNT];  &lt;/span&gt;&lt;span style="background: silver; color: green"&gt;//array of idle times&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;int &lt;/span&gt;&lt;span style="background: silver"&gt;half = INTERVAL / 2;&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;double &lt;/span&gt;&lt;span style="background: silver"&gt;radian = 0.0;&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;for &lt;/span&gt;&lt;span style="background: silver"&gt;(&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;int &lt;/span&gt;&lt;span style="background: silver"&gt;i = 0; i &amp;lt; COUNT; i++)&#xD;
            {&#xD;
                busySpan[i] = (&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;double&lt;/span&gt;&lt;span style="background: silver"&gt;)(half + (&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Math&lt;/span&gt;&lt;span style="background: silver"&gt;.Sin(PI * radian) * half));&#xD;
                idleSpan[i] = INTERVAL - busySpan[i];&#xD;
                radian += SPLIT;&#xD;
            }&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;double &lt;/span&gt;&lt;span style="background: silver"&gt;startTime = 0;&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;int &lt;/span&gt;&lt;span style="background: silver"&gt;j = 0;&#xD;
            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;while &lt;/span&gt;&lt;span style="background: silver"&gt;(&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;true&lt;/span&gt;&lt;span style="background: silver"&gt;)&#xD;
            {&#xD;
                j = j % COUNT;&#xD;
                startTime = &lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Environment&lt;/span&gt;&lt;span style="background: silver"&gt;.TickCount;&#xD;
                &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;while &lt;/span&gt;&lt;span style="background: silver"&gt;((&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Environment&lt;/span&gt;&lt;span style="background: silver"&gt;.TickCount - startTime) &amp;lt;= busySpan[j]) ;&#xD;
                System.Threading.&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Thread&lt;/span&gt;&lt;span style="background: silver"&gt;.Sleep((&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;int&lt;/span&gt;&lt;span style="background: silver"&gt;)idleSpan[j]);&#xD;
                j++;&#xD;
            }&#xD;
        }&#xD;
    }&#xD;
}&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;将这段代码直接F5， 运行结果如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/1_2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/1_thumb.png" width="282" height="304" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;果然，与大家意料的一样，两个CPU中都会显示出非常扭曲、不规则的正弦曲线。 &lt;/p&gt;&#xD;
&lt;p&gt;按照书中的说法，C++程序可以使用WinAPI里的SetThreadAffinityMast()函数，将程序固定到某个特定的CPU上执行。&lt;/p&gt;&#xD;
&lt;p&gt;查了下MSDN，当然，在.NET里，也有Manage的相似代码。见&lt;a href="http://msdn.microsoft.com/zh-tw/library/system.diagnostics.process.processoraffinity(VS.80).aspx" target="_blank"&gt;http://msdn.microsoft.com/zh-tw/library/system.diagnostics.process.processoraffinity(VS.80).aspx&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;按照MSDN，在代码中加入了简单的两句：&lt;/p&gt;&lt;pre &gt;&lt;span style="background: silver"&gt;     System.Diagnostics.&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Process &lt;/span&gt;&lt;span style="background: silver"&gt;p = System.Diagnostics.&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Process&lt;/span&gt;&lt;span style="background: silver"&gt;.GetCurrentProcess();             &#xD;
          p.ProcessorAffinity = (&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;IntPtr&lt;/span&gt;&lt;span style="background: silver"&gt;)0x0001;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste" target="_blank"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;然后再次F5, CPU中的曲线如下图所示：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/2_2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/2_thumb.png" width="282" height="304" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1号CPU成规则的正弦曲线相当完美，2号CPU使用率一直为0.&lt;/p&gt;&#xD;
&lt;p&gt;看来这就是书中想让大家达到的效果了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个效果让人感觉非常枯燥乏味。2号CPU的资源就浪费掉了，有没有办法将它利用起来呢？&lt;/p&gt;&#xD;
&lt;p&gt;让我们来分析这两句代码：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="background: silver"&gt;&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;while &lt;/span&gt;&lt;span style="background: silver"&gt;((&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Environment&lt;/span&gt;&lt;span style="background: silver"&gt;.TickCount - startTime) &amp;lt;= busySpan[j]) ; &lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="background: silver"&gt;System.Threading.&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Thread&lt;/span&gt;&lt;span style="background: silver"&gt;.Sleep((&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;int&lt;/span&gt;&lt;span style="background: silver"&gt;)idleSpan[j]); &lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;它的意思是，在规定好的时间间隔内（程序中规定了是100毫秒），满负载运行（通过空循环）构成正弦函数需要运行的时间（由之前的计算得到），其余时间就睡觉。如运行69毫秒，睡觉31毫秒，那么在这100毫秒的时间段，CPU的平均占用率就是69%。由于CPU占用率曲线是1秒钟更新一次的，程序使用的每100毫秒一个平均值节点，曲线的平滑度足够了。&lt;/p&gt;&#xD;
&lt;p&gt;继续发散。刚才的例子，如果是运行69毫秒，睡觉50毫秒呢？ 那么当前的100毫秒CPU占用率仍然会是69%，但如果算法不加调整，仍然以100毫秒为一个平均值节点，这就影响到了下一个100毫秒的CPU占用率。前一个影响后一个，如多米诺骨牌一样，整体的曲线就完全错误了。&lt;/p&gt;&#xD;
&lt;p&gt;也就是说，我们用来控制CPU平均占用率的时间段，每段必须相等。&lt;/p&gt;&#xD;
&lt;p&gt;我们考虑到以上的代码中，在1号CPU中运行了69毫秒，剩下了31毫秒如果转到2号CPU中运行，1号CPU的占用就会降到0，但与此同时我们就可以在2号CPU中&amp;#8220;画方&amp;#8221;了。 &lt;/p&gt;&#xD;
&lt;p&gt;概括起来说就是，当1号CPU小寐的时候，程序在2号CPU中&amp;#8220;画方&amp;#8221;；1号CPU小寐结束的时候，2号CPU中当前周期的&amp;#8220;方&amp;#8221;必须完成。&lt;/p&gt;&#xD;
&lt;p&gt;需要注意的是，假如1好CPU画了69毫秒，那么2号CPU一定只能画31毫秒。&lt;/p&gt;&#xD;
&lt;p&gt;按照这个思路，我们先实验一下简单的：在1号CPU中画正弦曲线后的休息时间段，我们在2号CPU中画余弦曲线。呵呵，初中学的三角函数你忘了吗？&lt;/p&gt;&#xD;
&lt;p&gt;我们将原代码中的空循环改为：&lt;/p&gt;&lt;pre &gt;&lt;span style="background: silver"&gt;            &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;while &lt;/span&gt;&lt;span style="background: silver"&gt;(&lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;true&lt;/span&gt;&lt;span style="background: silver"&gt;)&#xD;
            {&#xD;
                j = j % COUNT;&#xD;
                p.ProcessorAffinity = (&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;IntPtr&lt;/span&gt;&lt;span style="background: silver"&gt;)0x0001;&#xD;
                startTime = &lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Environment&lt;/span&gt;&lt;span style="background: silver"&gt;.TickCount;&#xD;
                &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;while &lt;/span&gt;&lt;span style="background: silver"&gt;((&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Environment&lt;/span&gt;&lt;span style="background: silver"&gt;.TickCount - startTime) &amp;lt;= busySpan[j]) ;&#xD;
                p.ProcessorAffinity = (&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;IntPtr&lt;/span&gt;&lt;span style="background: silver"&gt;)0x0002;&#xD;
                &lt;/span&gt;&lt;span style="background: silver; color: blue"&gt;while &lt;/span&gt;&lt;span style="background: silver"&gt;((&lt;/span&gt;&lt;span style="background: silver; color: #2b91af"&gt;Environment&lt;/span&gt;&lt;span style="background: silver"&gt;.TickCount - startTime) &amp;lt;= idleSpan[j]) ;&#xD;
                j++;&#xD;
            }&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste" target="_blank"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;&amp;#8220;左手正弦，右手余弦&amp;#8221;结果差强人意：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/image_6.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/image_thumb_2.png" width="328" height="354" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;我们注意到这个曲线没有之前单CPU运行时那么精确的。&lt;/p&gt;&#xD;
&lt;p&gt;原因是我们切换CPU的运营占用了时间。例如，以前正弦画了69毫秒，我们计算出余弦应该画31毫秒，但切换CPU的操作可能占用了3毫秒（或更多、或每次耗时都不同），整体就不在100毫秒这个间隔范围了，所以曲线结果有误差。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;到这里，我的思路已经说完了，相信大家已经明白。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;不过， 走到这一步，追求完美的我们，的确是遇到了一点障碍。&lt;/p&gt;&#xD;
&lt;p&gt;我经过一些周期上的微调，并且将余弦函数改为了简单的方波函数，最终效果正如本文开头展示的一样，还是不错的。&lt;/p&gt;&#xD;
&lt;p&gt;调整办法？呵呵，真不好意思，我暂时还没有想到一个足够说服大家、可以公式化的调整办法，就请各位看官在这里八仙过海，各显神通咯～&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/image_4.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/azure/WindowsLiveWriter/CPU_15113/image_thumb_1.png" width="328" height="354" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/azure/aggbug/1693365.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/azure/archive/2010/03/24/1693365.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
