日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

ESBasic 可復用的.NET類庫(14) -- 優先級管

系統 1723 0

1. 緣起:

假設我們的訂單處理系統所要處理的訂單是有優先級的,也就是說,不同的訂單類型所要求被處理的緊迫程度不同,對那些優先級高的注單要先處理,對于優先級低的注單可稍后處理。對于處于同一優先級的訂單了,就按照其到達的先后順序進行處理。

這是一個典型的管理具有優先級的對象的需求,注單就是具有優先級( With Priority )的對象。我設計了 ESBasic.ObjectManagement.Managers.IPriorityManager 優先級管理器(確切地說,應該稱之為“具有優先級對象的管理器”)來對類似的對象進行管理。

優先級管理器的形象示意圖如下:

ESBasic 可復用的.NET類庫(14) -- 優先級管理器 IPriorityManager

2. 適用場合:

如果你的系統需要對被管理的對象進行優先級分級,并滿足以下條件,則可使用 IPriorityManager

(1) 對象需要按優先級別( PriorityLevel )進行分類。

(2) 優先級別的劃分是固定的,不會隨系統的運行而發生變化。

(3) 對處于同一優先級別的對象,采用先來后到的順序進行“第二優先級”的高低確定。

(4) 優先級別可以使用 >=0 的連續整數來表示。

3 .設計思想與實現

在前面的敘述中,具有優先級對象的管理器的功能職責是相當清晰明了的,在進入其實現之前,首先我們要解決的一個問題是,如何對處于同一優先級別的對象進行管理。根據前面的需求描述,如果兩個對象處于相同的優先級別,則先到達的對象的優先程度(即所謂的“第二優先級”)更高。

我使用 ESBasic.ObjectManagement.Managers. ISamePriorityObjectManager (同一優先級別對象管理器)來管理屬于同一優先級別的所有對象,其接口定義如下:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> public interface ISamePriorityObjectManager < T >
{
/// <summary>
/// AddWaiter添加一個等待者。如果等待者在管理器中已經存在,則直接返回。
/// </summary>
void AddWaiter(Twaiter);

/// <summary>
/// Count當前管理器中等待者的數量。
/// </summary>
int Count{ get ;}

/// <summary>
/// GetNextWaiter返回等待時間最長的waiter。
/// 注意,返回時并不會從等待列表中刪除waiter。如果要刪除某個等待者,請調用RemoveWaiter。
/// </summary>
TGetNextWaiter();

/// <summary>
/// GetWaitersByPriority按照等待者加入的先后順序返回等待者數組,數組中index越小的等待者其等待時間越長,其優先級也越高。
/// </summary>
T[]GetWaitersByPriority();

/// <summary>
/// RemoveWaiter從管理器中移除指定的等待者。
/// </summary>
void RemoveWaiter(Twaiter);

/// <summary>
/// Clear清空管理器中的所有等待者。
/// </summary>
void Clear();

/// <summary>
/// Contains管理器中是否存在指定的等待者。
/// </summary>
bool Contains(Twaiter);
}

ISamePriorityObjectManager 所表述的語義環境中,被管理的對象稱為“等待者” waiter ――這表示一個對象等待被處理。

關于 SamePriorityObjectManager 的實現,有以下幾點需要說明:

(1) 其內部是使用 LinkedList 而不是 Queue 來存儲等待者的,其主要原因在于 SamePriorityObjectManager 需要支持移除管理器中任一等待者的 RemoveWaiter 方法。由于 Queue 本身不支持任意位置的刪除功能,所以我使用了 LinkedList 。新加入的等待者將被放在 LinkedList 的最后位置。

(2) 當管理器中沒有任何等待者時, GetNextWaiter 方法將返回 default(T) ,如果 T 是值類型,則此時 GetNextWaiter 返回的可能并不是一個你所期望的對象。所以,如果 T 是值類型,在調用 GetNextWaiter 之前先訪問一下其 Count 屬性確保管理器中還有等待者存在。

(3) SamePriorityObjectManager 使用了前面介紹的 SmartRWLocker 來對內部的 waiterList 進行讀寫鎖控制。

在討論完 SamePriorityObjectManager 的實現以后,我們將注意力轉移到本節的主角 IPriorityManager 上來, IPriorityManager 的接口定義如下:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> /// <summary>
/// IPriorityManager具有優先級的對象的管理器。
/// </summary>
/// <typeparamname="T"> 被管理的對象的類型,必須從IPriorityObject繼承。 </typeparam>
public interface IPriorityManager < T > : ISamePriorityObjectManager < T > where T: class , IPriorityObject
{
int PriorityLevelCount{ get ; set ;}
}

IPriorityManager 接口直接從 ISamePriorityObjectManager 繼承,并沒有多加任何方法,唯一增加的就是一個 PriorityLevelCount 屬性和要求被管理的對象的類型必須是從 IPriorityObject 接口繼承的一個泛型約束。

PriorityLevelCount 用于設定你的系統需要有幾種優先級別。比如,我的訂單基于緊急的優先級可分為緊急、普通、不緊急三種,那么就可將 PriorityLevelCount 屬性設置為 3

一個類型從 IPriorityObject 接口繼承,就表明它的實例是具有優先級屬性的對象。

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> /// <summary>
/// IPriorityObject具有優先級的對象的接口。
/// </summary>
public interface IPriorityObject
{
int PriorityLevel{ get ;}
}

為什么 ISamePriorityObjectManager 沒有要求被管理的對象繼承自 IPriorityObject 接口了? 這是因為在 ISamePriorityObjectManager 的職責中,其僅僅是根據對象的先后順序來確定“第二優先級”的,這并不是真正意義上的優先級別,所以沒有必要為其單獨抽象出一個 IPriorityObject 接口來。同時, ISamePriorityObjectManager 不要求被管理的對象繼承自 IPriorityObject 接口也是為了擴大其被單獨復用的范圍。

IPriorityManager 接口直接從 ISamePriorityObjectManager 接口繼承,說明 IPriorityManager 實際上要做工作與 ISamePriorityObjectManager 是相同的,只不過 IPriorityManager 管理的對象需要首先按優先級別進行分類,然后再使用 ISamePriorityObjectManager 管理處于同一優先級別的對象。

接下來我們看 PriorityManager 的具體實現。

PriorityManager 中,有這樣的一個 約定 :優先級別是用 int 表示的,其值是從 0 開始連續的一串整數,整數值越小,表明優先級越高。當 Initialize 方法被執行后,優先等級的范圍就被固定下來。比如 PriorityLevelCount 值設為 4 ,則 PriorityManager 所支持的優先等級即為: 0 1 2 3

基于這樣的約定, PriorityManager 內部使用了一個 ISamePriorityObjectManager 數組,數組的索引值就對應著優先級別值。比如,數組中 index 1 ISamePriorityObjectManager 管理器中的所有對象的優先級別值都是 1

有了這兩點認識,再看 PriorityManager 的源碼就相當容易了,下面是其中的關鍵點:

(1) 在類似 AddWaiter RemoveWaiter 這樣的方法實現中,都是先通過其參數對象的 PriorityLevel 屬性定位到對應的 ISamePriorityObjectManager 管理器,然后再做進一步的處理的。

(2) 如果目標對象的 PriorityLevel 屬性值超過了約定的范圍, PriorityManager 會根據當前的情況做靈活的處理。比如,如果是調用 AddWaiter 加入一個這樣的對象,則會拋出一個“不支持該優先級別”的異常;而如果是在類似 RemoveWaiter 這樣的方法中,則會忽略這個對象。

(3) 如果 PriorityManager 管理器中沒有任何對象時, PriorityManager GetNextWaiter 方法直接返回 null ,而不是 default(T) ,這是因為在 PriorityManager 定義的泛型約束中,要求 T 必須是一個引用類型。這就沒有了前面提到的 SamePriorityObjectManager GetNextWaiter 方法的返回值可能導致的問題。

(4) GetWaitersByPriority 方法返回的對象數組具有這樣的特征:優先級別越高的對象,其在數組中的位置索引就越小;同一優先級別的對象,加入時間越早的,其在數組中的位置索引越小。

4. 使用時的注意事項

(1) 如果你的系統僅僅需要按照對象的到達順序來決定先后處理的順序,那么直接使用 ISamePriorityObjectManager 就可以滿足需求了,沒有必要使用 IPriorityManager 這個更復雜的類。使用 ISamePriorityObjectManager 還有一個好處就是,被管理的對象不需要實現 IPriorityObject 接口,這樣使用起來會更加方便。

(2) 如果在你的系統中不是使用 0,1,2,3… 這樣的數值來表示優先級別的,那么你可以建立一個轉換映射來完成優先級別值到數字的轉換。并遵從 PriorityManager 所要求的約定。

(3) PriorityManager Initialize 方法一旦被調用后,其 PriorityLevelCount 屬性便不應該被修改。或者說,即使該屬性在之后被修改,也不會產生任何效果。

5. 擴展

優先級管理器 PriorityManager 暫時沒有任何擴展。

注:ESBasic源碼可到 http://esbasic.codeplex.com/ 下載。
ESBasic討論:37677395
ESBasic開源前言

ESBasic 可復用的.NET類庫(14) -- 優先級管理器 IPriorityManager


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 麦盖提县| 锡林郭勒盟| 临沂市| 股票| 普兰县| 衡阳市| 桂林市| 炎陵县| 新邵县| 镇安县| 体育| 富锦市| 荆州市| 扎囊县| 延吉市| 田东县| 五华县| 河津市| 保靖县| 鹤峰县| 沛县| 怀来县| 绍兴市| 哈密市| 天峻县| 浙江省| 建湖县| 巴塘县| 车险| 界首市| 罗平县| 平凉市| 邢台县| 广德县| 政和县| 固阳县| 彩票| 蒙阴县| 讷河市| 镇远县| 沅江市|