Welcome

首页 / 软件开发 / C# / 无废话C#设计模式之十一:Composite

无废话C#设计模式之十一:Composite2010-01-13 博客园 lovecherry意图

将对象组合成树形结构以表示“部分-整体”的层次结构。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>

{

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=============");

}

}

}