日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

(原创)无废话C#设计模式之十一:Composite

發(fā)布時(shí)間:2025/3/19 C# 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (原创)无废话C#设计模式之十一:Composite 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

無廢話C#設(shè)計(jì)模式之十一:Composite

?

意圖

?

?????? 將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。Composite模式使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。

?

場(chǎng)景

?

我們知道,一個(gè)網(wǎng)絡(luò)游戲通常會(huì)有多個(gè)游戲大區(qū)。每一個(gè)游戲大區(qū)會(huì)有很多游戲服務(wù)器(一個(gè)游戲大區(qū)就是一組游戲服務(wù)器)。每一個(gè)游戲服務(wù)器上會(huì)有不同的服務(wù)(可以是多個(gè)服務(wù))。這是一個(gè)明顯的部分-整體關(guān)系,假設(shè)我們現(xiàn)在需要制作一個(gè)服務(wù)器管理工具,用于顯示所有大區(qū)、服務(wù)器以及服務(wù)的信息,并且能開啟這些服務(wù)(可以是單獨(dú)開啟一個(gè)服務(wù),也可以是開啟整個(gè)服務(wù)器上的所有服務(wù),也可以是開啟整個(gè)大區(qū)的所有服務(wù))。

可以看到,游戲服務(wù)器和游戲大區(qū)都是一個(gè)組合對(duì)象,而游戲服務(wù)是最底層的節(jié)點(diǎn)。客戶端在開啟一個(gè)游戲大區(qū)服務(wù)的時(shí)候,必須和游戲服務(wù)器以及游戲服務(wù)進(jìn)行依賴,而在開啟游戲服務(wù)器上所有服務(wù)的時(shí)候,必須和游戲服務(wù)進(jìn)行依賴。試想一下,如果一個(gè)公司的總裁在管理上不但需要和各總監(jiān)以及經(jīng)理進(jìn)行溝通,還有和底層的員工溝通,那么總裁是不是會(huì)太忙碌了一點(diǎn)?由此,我們引入組合模式,使組合對(duì)象和單個(gè)對(duì)象具有一樣的表現(xiàn)形式。

?

示例代碼

?

using System;

using System.Collections.Generic;

using System.Text;

?

namespace CompositeExample

{

??? class Program

??? {

??????? static void Main(string[] args)

??????? {

??????????? Element server1 = new GameServer("GS1", "192.168.0.1");

??????????? server1.Add(new GameService("Lobby1", 1, "S5Lobby1"));

??????????? server1.Add(new GameService("Gate1", 2, "S5Gate1"));

??????????? server1.Add(new GameService("DataExchange1", 3, "S5DataExchange1"));

??????????? server1.Add(new GameService("Rank1", 4, "S5Rank1"));

??????????? server1.Add(new GameService("Log1", 5, "S5Log1"));

??????????? Element server2 = new GameServer("GS2", "192.168.0.2");

??????????? server2.Add(new GameService("Lobby2", 1, "S5Lobby2"));

??????????? server2.Add(new GameService("Gate2", 2, "S5Gate2"));

???? ???????server2.Add(new GameService("DataExchange2", 3, "S5DataExchange1"));

??????????? server2.Add(new GameService("Rank2", 4, "S5Rank2"));

??????????? server2.Add(new GameService("Log2", 5, "S5Log2"));

??????????? Element area = new GameArea("電信區(qū)");

??????????? area.Add(server1);

??????????? area.Add(server2);

??????????? area.Display();

??????????? area.Start();

??????????? area.Stop();

??????? }

??? }

?

??? abstract class Element

??? {

??????? protected string name;

?

??????? public Element(string name)

??????? {

??????????? this.name = name;

??????? }

?

??????? public abstract void Add(Element element);

??????? public abstract void Remove(Element element);

??????? public abstract void Display();

??????? public abstract void Start();

??????? public abstract void Stop();

??? }

?

??? class GameService : Element, IComparable<GameService>

??? {

??????? private int serviceType;

??????? private string serviceName;

?

??????? public GameService(string name, int serviceType, string serviceName)

??????????? : base (name)

??????? {

??????????? this.serviceName = serviceName;

??????????? this.serviceType = serviceType;

??????? }

?

??????? public override void Add(Element element)

??????? {

??????????? throw new ApplicationException("xxx");

??????? }

?

??????? public override void Remove(Element element)

??????? {

??????????? throw new ApplicationException("xxx");

??????? }

?

??????? public override void Display()

??????? {

??????????? Console.WriteLine(string.Format("name:{0},serviceType:{1},serviceName:{2}", name, serviceType, serviceName));

??????? }

?

??????? public override void Start()

??????? {

??????????? Console.WriteLine(string.Format("{0} started", name));

??????? }

?

??????? public override void Stop()

??????? {

??????????? Console.WriteLine(string.Format("{0} stopped", name));

??????? }

?

??????? public int CompareTo(GameService other)

??????? {

??????????? return other.serviceType.CompareTo(serviceType);

??????? }

??? }

?

??? class GameServer : Element

??? {

??????? private string serverIP;

??????? private List<GameService> serviceList = new List<GameService>();

?

??????? public GameServer(string name, string serverIP)

??????????? : base(name)

??????? {

???????????

??????????? this.serverIP = serverIP;

??????? }

???????

??????? public override void Add(Element element)

??????? {

??????????? serviceList.Add((GameService)element);

??????? }

?

??????? public override void Remove(Element element)

??????? {

??????????? serviceList.Remove((GameService)element);

??????? }

?

??????? public override void Display()

???? ???{

??????????? Console.WriteLine(string.Format("{0}{1}({2}){3}", new string('+', 10), name, serverIP, new string('+', 10)));

??????????? foreach (Element element in serviceList)

??????????? {

??????????????? element.Display();

??????????? }

??????? }

?

? ??????public override void Start()

??????? {

??????????? serviceList.Sort();

??????????? Console.WriteLine("=============Starting the whole " + name + "=============");

??????????? for (int i = 0; i < serviceList.Count; i++ )

??????????? {

??????????????? serviceList[i].Start();

??????????? }

??????????? Console.WriteLine("=============The whole " + name + " started=============");

??????? }

?

??????? public override void Stop()

??????? {

??????????? Console.WriteLine("=============Stopping the whole " + name + "=============");

??????????? for (int i = serviceList.Count -1; i >= 0; i--)

??????????? {

??????????????? serviceList[i].Stop();

??????????? }

??????????? Console.WriteLine("=============The whole " + name + " stopped=============");

??????? }

??? }

?

??? class GameArea : Element

??? {

??????? private List<GameServer> serverList = new List<GameServer>();

?

??????? public GameArea(string name)

??????????? : base(name) { }

?

??????? public override void Add(Element element)

??????? {

??????????? serverList.Add((GameServer)element);

??????? }

?

??????? public override void Remove(Element element)

??????? {

??????????? serverList.Remove((GameServer)element);

??????? }

?

??????? public override void Display()

??????? {

??????????? Console.WriteLine(new string('=',20));

??????????? Console.WriteLine("?????? " + name);

??????????? Console.WriteLine(new string('=', 20));

??????????? foreach (Element element in serverList)

??????????? {

??????????????? element.Display();

??????????? }

??????? }

?

??????? public override void Start()

??????? {

??????????? Console.WriteLine("=============Starting the whole " + name + "=============");

??????????? foreach (Element element in serverList)

??????????? {

??????????????? element.Start();

??????????? }

??????????? Console.WriteLine("=============The whole " + name + " started=============");

??????? }

?

??????? public override void Stop()

??????? {

??????????? Console.WriteLine("=============Stopping the whole " + name + "=============");

??????????? foreach (Element element in serverList)

??????????? {

??????????????? element.Stop();

??????????? }

??????????? Console.WriteLine("=============The whole " + name + " stopped=============");

??????? }

??? }

}

代碼執(zhí)行結(jié)果如下圖:

?

?

代碼說明

?

l???????? Element類型就是抽象構(gòu)件的角色,它給組合對(duì)象以及單個(gè)對(duì)象提供了一個(gè)一致的接口,使得它們都能有一致的行為。

l???????? 這里就出現(xiàn)一個(gè)問題,組合對(duì)象需要通過AddRemove方法來為其添加子節(jié)點(diǎn),而最底層的樹葉構(gòu)件下并沒有任何子節(jié)點(diǎn),在接口中定義這些操作子節(jié)點(diǎn)方法的方式叫做透明方式的合成模式,缺點(diǎn)就是不夠安全,容易在運(yùn)行時(shí)出現(xiàn)異常。如果把這些操作子節(jié)點(diǎn)的方法定義從抽象構(gòu)件中刪除,由各樹枝構(gòu)件來實(shí)現(xiàn)的話,就是安全方式的合成模式,缺點(diǎn)也就是不夠透明。具體怎么做還要根據(jù)自己的需求。

l???????? GameService當(dāng)然就是樹葉構(gòu)件,如果調(diào)用它的Add以及Remove方法會(huì)拋出一個(gè)異常。當(dāng)然,你也可以以其它方式來記錄這種邏輯錯(cuò)誤。

l???????? GameServer是一個(gè)樹枝構(gòu)件。一個(gè)游戲服務(wù)器上會(huì)有多個(gè)游戲服務(wù)。這里注意到一點(diǎn),在開啟服務(wù)器上所有服務(wù)的時(shí)候,我們對(duì)服務(wù)進(jìn)行了排序,排序是按照服務(wù)的類型進(jìn)行的。然后,我們按照服務(wù)類型從大到小的次序開啟了服務(wù)。一般一個(gè)網(wǎng)絡(luò)游戲的服務(wù)會(huì)有很多種,而這些服務(wù)的開啟是有先后次序的,先開記錄日志的服務(wù)、排名服務(wù)、再開數(shù)據(jù)交換的服務(wù)、最后才是大廳服務(wù)等。我們不可能讓用戶進(jìn)入大廳的時(shí)候沒有地方寫數(shù)據(jù)和日志吧。開啟服務(wù)是按照次序的,那么關(guān)閉服務(wù)也就是按照相反的次序了。

l???????? 從上面這點(diǎn),我們就可以看到組合模式的好處了,樹枝構(gòu)件在管理樹葉構(gòu)件的時(shí)候通常還會(huì)有一些邏輯,不會(huì)是簡(jiǎn)單的增加和刪除操作。如果這些工作交給客戶端去做的話,就太不合理了。

l???????? 最上層的樹枝構(gòu)件就是GameArea類型。它并沒有什么特殊的地方。

?

何時(shí)采用

?

l???????? 從代碼角度來說,如果類型之間組成了層次結(jié)構(gòu),你希望使用統(tǒng)一的接口來管理每一個(gè)層次的類型的時(shí)候。

l???????? 從應(yīng)用角度來說,如果你希望把一對(duì)多的關(guān)系轉(zhuǎn)化為一對(duì)一的關(guān)系的時(shí)候。

?

實(shí)現(xiàn)要點(diǎn)

?

l???????? 使用透明模式還是安全模式根據(jù)自己的需要定。

l???????? 在某些情況下,樹葉構(gòu)件可以訪問樹枝構(gòu)件獲取一些信息。

l???????? 如果樹葉構(gòu)件數(shù)量比較多,樹枝構(gòu)件頻繁遍歷子節(jié)點(diǎn)的話可以考慮進(jìn)行緩存。

l???????? 既然所有對(duì)象有了統(tǒng)一的接口,客戶端應(yīng)該針對(duì)抽象構(gòu)件進(jìn)行編程。

?

注意事項(xiàng)

?

l????????

總結(jié)

以上是生活随笔為你收集整理的(原创)无废话C#设计模式之十一:Composite的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。