首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 設計模式實戰:Composite 組合模式完整解析(一)

     編輯:關於C語言

模式意圖

將物件組合成樹形結構以表示「部分-整體」層次,使 Client 對單一物件與組合物件具有一致性使用方式。

應用場景:遊戲伺服器管理工具

多大區 → 多伺服器 → 多服務(Log、Rank、DataExchange、Gate、Lobby)。需求:顯示所有資訊,支援單一服務/整台伺服器/整個大區的啟動與停止。

若 Client 直接依賴具體層級,總裁級管理者將需與底層員工直接溝通。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 // Component
    {
        protected string _name;
        public Element(string name) { _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> // Leaf
    {
        private int _serviceType;
        private string _serviceName;
        public GameService(string name, int serviceType, string serviceName) : base(name)
        { _serviceName = serviceName; _serviceType = serviceType; }

        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 // Composite
    {
        private string _serverIP;
        private List<GameService> _services = new List<GameService>();
        public GameServer(string name, string serverIP) : base(name) { _serverIP = serverIP; }

        public override void Add(Element e) => _services.Add((GameService)e);
        public override void Remove(Element e) => _services.Remove((GameService)e);
        public override void Display()
        {
            Console.WriteLine(new string('+', 10) + _name + "(" + _serverIP + ")" + new string('+', 10));
            foreach (var e in _services) e.Display();
        }
        public override void Start()
        {
            _services.Sort();
            Console.WriteLine("=============Starting " + _name + "=============");
            foreach (var s in _services) s.Start();
            Console.WriteLine("=============" + _name + " started=============");
        }
        public override void Stop()
        {
            Console.WriteLine("=============Stopping " + _name + "=============");
            for (int i = _services.Count - 1; i >= 0; i--) _services[i].Stop();
            Console.WriteLine("=============" + _name + " stopped=============");
        }
    }

    class GameArea : Element // Composite (Root)
    {
        private List<GameServer> _servers = new List<GameServer>();
        public GameArea(string name) : base(name) { }

        public override void Add(Element e) => _servers.Add((GameServer)e);
        public override void Remove(Element e) => _servers.Remove((GameServer)e);
        public override void Display()
        {
            Console.WriteLine(new string('=', 20));
            Console.WriteLine(" " + _name);
            Console.WriteLine(new string('=', 20));
            foreach (var e in _servers) e.Display();
        }
        public override void Start()
        {
            Console.WriteLine("=============Starting " + _name + "=============");
            foreach (var e in _servers) e.Start();
            Console.WriteLine("=============" + _name + " started=============");
        }
        public override void Stop()
        {
            Console.WriteLine("=============Stopping " + _name + "=============");
            foreach (var e in _servers) e.Stop();
            Console.WriteLine("=============" + _name + " stopped=============");
        }
    }
}

關鍵設計決策

  • IComparable<GameService> 實現服務啟動順序排序
  • 透明模式:Leaf 也實作 Add/Remove(拋例外)
  • 遞迴結構:Display/Start/Stop 自然向下傳遞
  • Client 僅持有根節點 area,一鍵操作整棵樹
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved