首页
技术库|站长工具|技术手册|字体库|知识点词汇表| 联系我们|
打开本页的html静态页面
 

主菜单

文章分类

.: .Net技术 .: .Net分析与设计 .: C#设计模式专题之二十一:Visitor模式

  • 全文内容
  • 发表评论
  • 文章点评
  • 文章附件
  • Email文章
  • 打印文章

C#设计模式专题之二十一:Visitor模式

点击次数:330 创建日期:11-17-2007 录入:cn-web.com 字体:[ ] 点评:


C#设计模式学习专题(转自互联网)


意图

 

       实现通过统一的接口访问不同类型元素的操作,并且通过这个接口可以增加新的操作而不改变元素的类。

 

场景

 

想不出什么好例子,我们在组合模式的那个例子上进行修改吧。我们知道,无论是游戏大区、游戏服务器还是游戏的服务都是一个元素,只不过它们的层次不一样。对于这样的层次结构,我们使用了组合模式来统一各层的接口,这样对游戏大区的操作和对游戏服务器的操作对调用方来说没有什么两样。在现实中,组合模式的运用往往没有这么顺利:

l         如果元素需要增加新的操作,那么势必需要在抽象元素中增加接口,这个时候的改动就非常大了,几乎每一个具体元素都需要修改。

l         如果元素并没有统一的接口,并且树枝角色中有多种树叶角色,那么树枝角色势必需要根据树叶类型来调用不同的方法。

l         如果树叶角色的接口经常发生变动,那么一旦发生变动操作树叶的树枝角色也需要发生修改。

访问者模式可以解决这些问题。

 

示例代码

 

using System;

using System.Collections;

using System.Collections.Generic;

using System.Text;

 

namespace VisitorExample

{

    class Program

    {

        static void Main(string[] args)

        {

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

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

            server1.Add(new GameService("Lobby2", 1, "S5Lobby2", 200));

            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("Lobby3", 1, "S5Lobby3", 150));

            server2.Add(new GameService("Lobby4", 1, "S5Lobby4", 250));

            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.Accept(new StartGameVisitor()); //A1

            area.Accept(new StopGameVisitor()); //B1

            server1.Accept(new QueryPlayerCountVisitor());

            server2.Accept(new QueryPlayerCountVisitor());

            area.Accept(new QueryPlayerCountVisitor());

        }

}

 

    interface IVisitor { }

 

    interface IGameServiceVisitor

    {

        void Visit(GameService gameService);

    }

 

    interface IGameServerVisitor

    {

        void Visit(GameServer gameServer);

    }

 

    interface IGameAreaVisitor

    {

        void Visit(GameArea gameArea);

    }

 

    class StartGameVisitor : IVisitor, IGameServiceVisitor, IGameServerVisitor, IGameAreaVisitor

    {

        public void Visit(GameService gameService)

        {

            //A9

            gameService.StartGameService(this);

        }

 

        public void Visit(GameServer gameServer)

        {

            //A6

            gameServer.StartGameServer(this);

        }

 

        public void Visit(GameArea gameArea)

        {

            //A3

            gameArea.StartGameArea(this);

        }  

 }

 

    class StopGameVisitor : IVisitor, IGameServiceVisitor, IGameServerVisitor, IGameAreaVisitor

    {

        public void Visit(GameService gameService)

        {

            //B7

            Console.WriteLine(string.Format("{0} stopped", gameService.Name));

        }

 

        public void Visit(GameServer gameServer)

        {

            //B5

            Console.WriteLine("=============Stopping the whole "+ gameServer.Name + "=============");

            for (int i = gameServer.ServiceList.Count - 1; i >= 0; i--)

            {

                gameServer.ServiceList[i].Accept(this);

            }

            Console.WriteLine("=============The whole "+ gameServer.Name + " stopped=============");

        }

 

        public void Visit(GameArea gameArea)

        {

            //B3

            Console.WriteLine("=============Stopping the whole "+ gameArea.Name + "=============");

            foreach (GameServer element in gameArea.ServerList)

            {

                element.Accept(this);

            }

            Console.WriteLine("=============The whole "+ gameArea.Name + " stopped=============");

        }

}

 

    class QueryPlayerCountVisitor : IVisitor, IGameServerVisitor, IGameAreaVisitor

    {

        public void Visit(GameServer gameServer)

        {

            int playerCount = 0;

            foreach (GameService gameService in gameServer)

            {

                if (gameService.ServiceType == 1)

                    playerCount += gameService.PlayerCount;

            }

            Console.WriteLine("=============Player Count on "+ gameServer.Name + " is:"+ playerCount);

        }

 

        public void Visit(GameArea gameArea)

        {

            int playerCount = 0;

            foreach (GameServer gameServer in gameArea)

            {

                foreach (GameService gameService in gameServer)

                {

                    if (gameService.ServiceType == 1)

                        playerCount += gameService.PlayerCount;

                }

            }

            Console.WriteLine("=============Player Count on "+ gameArea.Name + " is:"+ playerCount);

        }

    }

 

    abstract class Element

    {

        protected string name;

 

        public string Name

        {

            get { return name; }

        }

 

        public Element(string name)

        {

            this.name = name;

        }

 

        public abstract void Add(Element element);

        public abstract void Remove(Element element);

        public abstract void Accept(IVisitor visitor);

    }

 

    class GameService : Element, IComparable<GameService>

    {