无废话C#设计模式之二十一Visitor.docx
《无废话C#设计模式之二十一Visitor.docx》由会员分享,可在线阅读,更多相关《无废话C#设计模式之二十一Visitor.docx(12页珍藏版)》请在冰豆网上搜索。
无废话C#设计模式之二十一Visitor
无废话C#设计模式之二十一:
Visitor
无废话C#设计模式之二十一:
Visitor
意图
实现通过统一的接口访问不同类型元素的操作,并且通过这个接口可以增加新的操作而不改变元素的类。
场景
想不出什么好例子,我们在组合模式的那个例子上进行修改吧。
我们知道,无论是游戏大区、游戏服务器还是游戏的服务都是一个元素,只不过它们的层次不一样。
对于这样的层次结构,我们使用了组合模式来统一各层的接口,这样对游戏大区的操作和对游戏服务器的操作对调用方来说没有什么两样。
在现实中,组合模式的运用往往没有这么顺利:
l如果元素需要增加新的操作,那么势必需要在抽象元素中增加接口,这个时候的改动就非常大了,几乎每一个具体元素都需要修改。
l如果元素并没有统一的接口,并且树枝角色中有多种树叶角色,那么树枝角色势必需要根据树叶类型来调用不同的方法。
l如果树叶角色的接口经常发生变动,那么一旦发生变动操作树叶的树枝角色也需要发生修改。
访问者模式可以解决这些问题。
示例代码
usingSystem;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingSystem.Text;
namespaceVisitorExample
{
classProgram
{
staticvoidMain(string[]args)
{
Elementserver1=newGameServer("GS1","192.168.0.1");
server1.Add(newGameService("Lobby1",1,"S5Lobby1",100));
server1.Add(newGameService("Lobby2",1,"S5Lobby2",200));
server1.Add(newGameService("Gate1",2,"S5Gate1"));
server1.Add(newGameService("DataExchange1",3,"S5DataExchange1"));
server1.Add(newGameService("Rank1",4,"S5Rank1"));
server1.Add(newGameService("Log1",5,"S5Log1"));
Elementserver2=newGameServer("GS2","192.168.0.2");
server2.Add(newGameService("Lobby3",1,"S5Lobby3",150));
server2.Add(newGameService("Lobby4",1,"S5Lobby4",250));
server2.Add(newGameService("Gate2",2,"S5Gate2"));
server2.Add(newGameService("DataExchange2",3,"S5DataExchange1"));
server2.Add(newGameService("Rank2",4,"S5Rank2"));
server2.Add(newGameService("Log2",5,"S5Log2"));
Elementarea=newGameArea("电信区");
area.Add(server1);
area.Add(server2);
area.Accept(newStartGameVisitor());//A1
area.Accept(newStopGameVisitor());//B1
server1.Accept(newQueryPlayerCountVisitor());
server2.Accept(newQueryPlayerCountVisitor());
area.Accept(newQueryPlayerCountVisitor());
}
}
interfaceIVisitor{}
interfaceIGameServiceVisitor
{
voidVisit(GameServicegameService);
}
interfaceIGameServerVisitor
{
voidVisit(GameServergameServer);
}
interfaceIGameAreaVisitor
{
voidVisit(GameAreagameArea);
}
classStartGameVisitor:
IVisitor,IGameServiceVisitor,IGameServerVisitor,IGameAreaVisitor
{
publicvoidVisit(GameServicegameService)
{
//A9
gameService.StartGameService(this);
}
publicvoidVisit(GameServergameServer)
{
//A6
gameServer.StartGameServer(this);
}
publicvoidVisit(GameAreagameArea)
{
//A3
gameArea.StartGameArea(this);
}
}
classStopGameVisitor:
IVisitor,IGameServiceVisitor,IGameServerVisitor,IGameAreaVisitor
{
publicvoidVisit(GameServicegameService)
{
//B7
Console.WriteLine(string.Format("{0}stopped",gameService.Name));
}
publicvoidVisit(GameServergameServer)
{
//B5
Console.WriteLine("=============Stoppingthewhole"+gameServer.Name+
"=============");
for(inti=gameServer.ServiceList.Count-1;i>=0;i--)
{
gameServer.ServiceList[i].Accept(this);
}
Console.WriteLine("=============Thewhole"+gameServer.Name+"stopped=============");
}
publicvoidVisit(GameAreagameArea)
{
//B3
Console.WriteLine("=============Stoppingthewhole"+gameArea.Name+"=============");
foreach(GameServerelementingameArea.ServerList)
{
element.Accept(this);
}
Console.WriteLine("=============Thewhole"+gameArea.Name+"stopped=============");
}
}
classQueryPlayerCountVisitor:
IVisitor,IGameServerVisitor,IGameAreaVisitor
{
publicvoidVisit(GameServergameServer)
{
intplayerCount=0;
foreach(GameServicegameServiceingameServer)
{
if(gameService.ServiceType==1)
playerCount+=gameService.PlayerCount;
}
Console.WriteLine("=============PlayerCounton"+gameServer.Name+"is:
"+
playerCount);
}
publicvoidVisit(GameAreagameArea)
{
intplayerCount=0;
foreach(GameServergameServeringameArea)
{
foreach(GameServicegameServiceingameServer)
{
if(gameService.ServiceType==1)
playerCount+=gameService.PlayerCount;
}
}
Console.WriteLine("=============PlayerCounton"+gameArea.Name+"is:
"+
playerCount);
}
}
abstractclassElement
{
protectedstringname;
publicstringName
{
get{returnname;}
}
publicElement(stringname)
{
this.name=name;
}
publicabstractvoidAdd(Elementelement);
publicabstractvoidRemove(Elementelement);
publicabstractvoidAccept(IVisitorvisitor);
}
classGameService:
Element,IComparable
{
privateintserviceType;
publicintServiceType
{
get{returnserviceType;}
set{serviceType=value;}
}
privatestringserviceName;
privateintplayerCount;
publicintPlayerCount
{
get{returnplayerCount;}
set{playerCount=value;}
}
publicGameService(stringname,intserviceType,stringserviceName)
:
base(name)
{
this.serviceName=serviceName;
this.serviceType=serviceType;
}
publicGameService(stringname,intserviceType,stringserviceName,intplayerCount)
:
base(name)
{
this.serviceName=serviceName;
this.serviceType=serviceType;
this.playerCount=playerCount;
}
publicoverridevoidAdd(Elementelement)
{
thrownewApplicationException("xxx");
}
publicoverridevoidRemove(Elementelement)
{
thrownewApplicationException("xxx");
}
publicoverridevoidAccept(IVisitorvisitor)
{
//A8,B6
IGameServiceVisitorgameServiceVisitor=visitorasIGameServiceVisitor;
if(gameServiceVisitor!
=null)gameServiceVisitor.Visit(this);
}
publicintCompareTo(GameServiceother)
{
returnother.serviceType.CompareTo(serviceType);
}
publicvoidStartGameService(IVisitorvisitor)
{
//A10
Console.WriteLine(string.Format("{0}started",name));
}
}
classGameServer:
Element
{
privatestringserverIP;
privateListserviceList=newList();
publicListServiceList
{
get{returnserviceList;}
}
publicGameServer(stringname,stringserverIP)
:
base(name)
{
this.serverIP=serverIP;
}
publicoverridevoidAdd(Elementelement)
{
serviceList.Add((GameService)element);
}
publicoverridevoidRemove(Elementelement)
{
serviceList.Remove((GameService)element);
}
publicoverridevoidAccept(IVisitorvisitor)
{
//A5,B5
IGameServerVisitorgameServerVisitor=visitorasIGameServerVisitor;
if(gameServerVisitor!
=null)gameServerVisitor.Visit(this);
}
publicIEnumeratorGetEnumerator()
{
foreach(GameServicegameServiceinserviceList)
yieldreturngameService;
}
publicvoidStartGameServer(IVisitorvisitor)
{
//A7
IGameServerVisitorgameServerVisitor=visitorasIGameServerVisitor;
if(gameServerVisitor!
=null)
{
serviceList.Sort();
Console.WriteLine("=============Startingthewhole"+name+"=============");
foreach(ElementgameServiceinserviceList)
{
gameService.Accept(visitor);
}
Console.WriteLine("=============Thewhole"+name+"started=============");
}
}
}
classGameArea:
Element
{
privateListserverList=newList();
publicListServerList
{
get{returnserverList;}
}
publicGameArea(stringname)
:
base(name){}
publicoverridevoidAdd(Elementelement)
{
serverList.Add((GameServer)element);
}
publicoverridevoidRemove(Elementelement)
{
serverList.Remove((GameServer)element);
}
publicoverridevoidAccept(IVisitorvisitor)
{
//A2,B2
IGameAreaVisitorgameAreaVisitor=visitorasIGameAreaVisitor;
if(gameAreaVisitor!
=null)gameAreaVisitor.Visit(this);
}
publicIEnumeratorGetEnumerator()
{
foreach(GameServergameServerinserverList)
yieldreturngameServer;
}
publicvoidStartGameArea(IVisitorvisitor)
{
//A4
IGameAreaVisitorgameAreaVisitor=visitorasIGameAreaVisitor;
if(gameAreaVisitor!
=null)
{
Console.WriteLine("=============Startingthewhole"+name+"=============");
foreach(ElementgameServerinserverList)
{
gameServer.Accept(visitor);
}
Console.WriteLine("=============Thewhole"+name+"started=============");
}
}
}
}