1.緣起:
假設我們要開發一個多人跳棋游戲。在跳棋游戲中,當一個人走一步棋之后,控制權就輪到下一家,如此輪詢,一圈之后控制權又回到自己,然后再繼續輪圈下去。我們可以使用數組或列表等數據結構來解決這種轉圈圈的問題,但是始終都不夠直觀。
我設計了Circle來對“圈”這種數據結構進行抽象,我們在類似跳棋這樣的游戲中可以非常方便地直接使用它。
Circle的形象示意圖如下:
2.適用場合:
需要類似“圈”這樣的數據結構支持的場合。
3.設計思想與實現
Circle也是一個非常簡單的數據結構,其類圖如下所示:
從類圖中顯示的Header和Tail屬性,我們看出Circle就像一個真正的現實中焊接而成的鐵圈一樣,是有結合點的,這個結合點就是Tail與Header交接的地方。
Append方法用于將一個新的對象附加到Tail后面,于是這個新的對象就變成了真正的Tail。
Insert方法用于在指定的地方插入一個新對象,如果當前Circle中沒有任何對象,則無論其指定的位置是哪里,都將被放置在Header的位置。
SetCurrent方法用于將控制權轉交給參數指定的對象。如果指定的對象在Circle中不存在,則SetCurrent將不執行任何操作。
MoveNext方法和MoveBack方法表示將控制權轉移到下一家或上一家。
PeekNext方法和PeekBack方法與MoveNext、MoveBack含義不一樣的地方在于:MoveNext、MoveBack轉移了控制權,而PeekNext和PeekBack沒有,它們只是返回下一家或上一家對象。
關于Circle的實現要注意以下幾點:
(1)Circle的內部是使用List來存放對象的。
(2)Circle沒有進行任何加鎖控制,所以它不是線程安全的。我們類似跳棋這樣轉圈圈的游戲,通常都是以一個有序的順序來控制游戲的進行的,很少出現多個線程同時修改一個Circle的控制權的情況,所以在類似這樣的環境中,Circle就不需要加鎖了。
(3)注意,InsertAt方法和RemoveAt方法接收的參數postionIndex的值允許比內部List的最大索引值還大,它們在實現時會對postionIndex進行求模運算,將postionIndex修正到正確的范圍內,在對List進行Insert和Remove操作。
4. 使用時的注意事項
(1)Insert方法并不會改變Circle的當前對象(即Current屬性的值)。
(2)當Circle中不包含任何元素時,Header、Tail和Current屬性返回的都是default(T)。如果T是引用類型,則這個值是null。
(3)當Circle中只包含一個元素時,Header和Tail屬性將返回同一個對象。
5.擴展
圈Circle暫時沒有任何擴展。
在我們后面介紹的CircleTaskSwitcher(循環任務切換器),它的實現就用到了本節的Circle。
注: ESBasic已經開源,點擊這里下載源碼。
![]() |
不含病毒。www.avast.com |