將對象組合成樹形結構以表示「部分-整體」層次,使客戶端對單個對象與組合對象使用具有一致性。
遊戲大區→伺服器→服務 三層結構。管理工具需顯示所有資訊、啟動服務(單服務/整伺服器/整大區)。若客戶端直接依賴各層,如總裁既管總監也管底層員工,過於繁瑣。引入 Composite 統一介面。
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("電信區");
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>
{
int serviceType; string serviceName;
public GameService(string name, int type, string sName) : base(name) { serviceType = type; serviceName = sName; }
public override void Add(Element e) => throw new ApplicationException("Leaf cannot add");
public override void Remove(Element e) => throw new ApplicationException("Leaf cannot remove");
public override void Display() => Console.WriteLine($"name:{Name},serviceType:{serviceType},serviceName:{serviceName}");
public override void Start() => Console.WriteLine($"{Name} started");
public override void Stop() => Console.WriteLine($"{Name} stopped");
public int CompareTo(GameService other) => other.serviceType.CompareTo(serviceType);
}
class GameServer : Element
{
string serverIP; List<GameService> serviceList = new List<GameService>();
public GameServer(string name, string ip) : base(name) { serverIP = ip; }
public override void Add(Element e) => serviceList.Add((GameService)e);
public override void Remove(Element e) => serviceList.Remove((GameService)e);
public override void Display()
{
Console.WriteLine($"{new string('+',10)}{Name}({serverIP}){new string('+',10)}");
foreach (var e in serviceList) e.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
{
List<GameServer> serverList = new List<GameServer>();
public GameArea(string name) : base(name) { }
public override void Add(Element e) => serverList.Add((GameServer)e);
public override void Remove(Element e) => serverList.Remove((GameServer)e);
public override void Display()
{
Console.WriteLine(new string('=',20));
Console.WriteLine($" {Name}");
Console.WriteLine(new string('=',20));
foreach (var e in serverList) e.Display();
}
public override void Start()
{
Console.WriteLine($"=============Starting the whole {Name}=============");
foreach (var e in serverList) e.Start();
Console.WriteLine($"=============The whole {Name} started=============");
}
public override void Stop()
{
Console.WriteLine($"=============Stopping the whole {Name}=============");
foreach (var e in serverList) e.Stop();
Console.WriteLine($"=============The whole {Name} stopped=============");
}
}
}
Add/Remove/Display/Start/Stop)。Add/Remove 為透明模式(葉節點執行拋異常),移除則為安全模式(葉節點無此介面)。視需求取捨。Add/Remove 拋異常。實作 IComparable 供排序(按服務類型)。Start 依類型排序後按序啟動(日誌→排名→數據交換→大廳);Stop 逆序關閉。體現分支節點的管理邏輯不只是增刪。