专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »DotNet » 无废话C#设计模式的 2十:Mediator »正文

无废话C#设计模式的 2十:Mediator

来源: 发布时间:星期五, 2009年4月3日 浏览:0次 评论:0
  意图

   用个中介对象来封装系列对象交互中介者使得各对象不需要显式相互引用从而使其松散耦合而且可以独立地改变它们的间交互

  场景

  我们知道个网络游戏往往有很多大区个大区可以是组服务器也可以是多组服务器在这里假设个大区是组服务器为了效率般每个大区都会有个数据库玩家创建角色、充值、消费行为只是在这个大区中有效现在公司有了新需求那就是玩家些信息能在多个大区中共享比如在注册时候就把玩家账户信息写入多个信息共享大区玩家在某个大区中充值需要“通知”其它大区修改账户余额玩家在某个大区中消费也需要“通知”其它大区修改账户余额

  如果我们现在有ABC 3个大区下面思路方法可以实现需求:

  l         网站WebSite注册思路方法A、B和C大区注册思路方法

  l         A大区充值思路方法B和C充值思路方法

  l         B大区充值思路方法A和C充值思路方法

  l         C大区充值思路方法A和B充值思路方法

  l         A大区消费思路方法B和C充值思路方法

  l         B大区消费思路方法A和C充值思路方法

  l         C大区消费思路方法A和B充值思路方法

  我想没有人会这么做吧你肯定会想到在个统地方去维护所有大区信息任何个大区行为不直接和其它大区行为关联它们所有行为都提交到个统地方(假设它是Account)去处理这么做有几个好处:

  l         各大区不需要关心还有哪些其它大区它只直接和Account对话

  l         只需要调整Account就能调整各大区的间交互行为比如我们仅仅希望A和B大区共享信息、C和D大区共享信息那么对于这种交互策略改变也需要修改Account

  l         有利于大区扩充有了新大区后我们不用在大区中考虑它交互行为交给Account去安排

  现在再来看看引入Account通讯:

  l         网站WebSiteAccount注册思路方法(1)

  l         AccountA、B和C大区注册思路方法(2)

  l         A、B和C大区充值思路方法Account充值思路方法(3)

  l         A、B和C大区消费思路方法Account充值思路方法(4)

  l         Account充值思路方法A、B和C大区专有充值思路方法(只针对本大区充值)(5)

  l         Account充值思路方法A、B和C大区专有消费思路方法(只针对本大区消费)(6)

  至此你已经实现了中介者模式你可能会觉得(1)和(2)非常类似门面模式没错它确实就是门面模式而有了(3)~(6)行为Account也就是个中介者角色了

  举例代码

using ;

using .Collections.Generic;

using .Text;

 

MediatorExample

{

    Program

    {

        void Main( args)

        {

            Account account = Account;

            Game gameArea1 = GameArea1(account);

            Game gameArea2 = GameArea2(account);

            account.RegisterGameArea(gameArea1);

            account.RegisterGameArea(gameArea2);

            userName = "aaa";

            account.CreateAccount(userName);

            gameArea1.Recharge(userName, 200);

            gameArea2.Consume(userName, 50);

            account.QueryBalance(userName);

        }

}

 

    Account

    {

        private Dictionary<, > userBalance = Dictionary<, >;

        private List<Game> gameAreaList = List<Game>;

 

        public void RegisterGameArea(Game gs)

        {

            gameAreaList.Add(gs);

        }

 

        public void CreateAccount( userName)

        {

            userBalance.Add(userName, 0);

            foreach (Game gs in gameAreaList)

                gs.CreateAccountSelf(userName);

        }

 

        public void Recharge( userName, amount)

        {

            (userBalance.ContainsKey(userName))

            {

                bool ok = true;

                foreach (Game gs in gameAreaList)

                    ok = gs.RechargeSelf(userName, amount);

                (ok)

                    userBalance[userName] amount;

            }

        }

 

        public void Consume( userName, amount)

        {

            (userBalance.ContainsKey(userName))

            {

                bool ok = true;

                foreach (Game gs in gameAreaList)

                    ok = gs.ConsumeSelf(userName, amount);

                (ok)

                    userBalance[userName] -= amount;

            }

        }

 

        public void QueryBalance( userName)

        {

            Console.WriteLine("Your balance is " + userBalance[userName]);

        }

    }

    abstract Game

    {

        private Account account;

        protected Dictionary<, > userBalance = Dictionary<, >;

 

        public Game(Account account)

        {

            this.account = account;

        }

 

        ernal virtual bool CreateAccountSelf( userName)

        {

            userBalance.Add(userName, 0);

            true;

        }

 

        ernal virtual bool RechargeSelf( userName, amount)

        {

            (userBalance.ContainsKey(userName))

                userBalance[userName] amount;

            true;

        }

 

        ernal virtual bool ConsumeSelf( userName, amount)

        {

            (userBalance.ContainsKey(userName))

                userBalance[userName] -= amount;

            true;

        }

 

        public void Recharge( userName, amount)

        {

            account.Recharge(userName, amount);

        }

 

        public void Consume( userName, amount)

        {

            account.Consume(userName, amount);

        }

    }

 

    GameArea1 : Game

    {

        public GameArea1(Account account) : base(account) { }

 

        ernal override bool CreateAccountSelf( userName)

        {

            Console.WriteLine(userName + " Registered in GameAre1");

            base.CreateAccountSelf(userName);

        }

 

        ernal override bool RechargeSelf( userName, amount)

        {

            base.RechargeSelf(userName, amount);

            Console.WriteLine(userName + "'s amount in GameArea1 is " + userBalance[userName]);

            true;

        }

 

        ernal override bool ConsumeSelf( userName, amount)

        {

            base.ConsumeSelf(userName, amount);

            Console.WriteLine(userName + "'s amount in GameArea1 is " + userBalance[userName]);

            true;

        }

}

 

    GameArea2 : Game

    {

        public GameArea2(Account account) : base(account) { }

 

        ernal override bool CreateAccountSelf( userName)

        {

            Console.WriteLine(userName + " Registered in GameAre2");

            base.CreateAccountSelf(userName);

 

        }

 

        ernal override bool RechargeSelf( userName, amount)

        {

            base.RechargeSelf(userName, amount);

            Console.WriteLine(userName + "'s amount in GameArea2 is " + userBalance[userName]);

            true;

        }

 

        ernal override bool ConsumeSelf( userName, amount)

        {

            base.ConsumeSelf(userName, amount);

            Console.WriteLine(userName + "'s amount in GameArea2 is " + userBalance[userName]);

            true;

        }

    }

}


  代码执行结果如下图:

无废话C#设计模式的 2十:Mediator

  代码介绍说明

  l         Account个中介者角色它负责各个同事类的间交互要使同事对象参和它管理就需要在内部维护个同事对象列表

  l         我们看到Account注册、充值和消费思路方法会遍历相关同事对象并且它们专有思路方法进行操作在全部操作完成的后它才会更新自己账户

  l         Game个抽象同事充值和消费思路方法都有两种种是给外部充值和消费思路方法种是给外部另外种是给Account在对外思路方法中Game仅仅是把这个请求转发给中介者它自己不做实质性操作而在xxxSelf思路方法中才做真正充值、消费操作

  l         GameArea1和GameArea2是具体同事父类构造思路方法来和中介者关联

  l         中介者模式特点就是同事自己意识到它需要和个中介者关联而在实际操作过程中它们只是负责和中介者通讯并且接受中介者请求而不再和其它同事发生直接关联

  何时采用

   如果组接口相对稳定(如果GameArea1和GameArea2充值思路方法定义不那么Account就有点晕眩了)对象的间依赖关系错综复杂依赖关系难以维护或者会发生变动可以考虑引入中介者模式

  实现要点

  l         在C#中可以适用delegate关联中介者和各同事的间交互行为这样各同事就不需要直接和中介者进行耦合

  l         中介者模式和观察者模式区别是前者应用于多对多杂乱交互行为统筹处理后者应用于(多)对多关系灵活定制对于本例来说集中处理后还需要分散处理那么后半阶段处理过程可以应用观察者模式对于前例子来说如果有多个主体角色和多个观察者进行多对多通讯也可以应用中介者模式来统筹这个多对多过程(大家可以自己尝试修改前例子来应用中介者模式)

  l         中介者模式和门面模式区别是前者各同事类需要依靠中介者进行双向通讯应用于子系统的间而后者子系统往往不会通过门面去和方进行通讯趋向于单向通讯应用于子系列和更高层次系统本例中就有门面模式和中介者模式影子

  l         中介者模式往往可以在构架层次进行应用时候和观察者模式以及门面模式起使用时候又会向观察者模式和门面模式退化其实在应用模式过程中不必过多考虑模式准确定位如果我们确实从中得以那么这个名字就不重要了

  注意事项

  l         不是所有系统都需要应用中介者模式把多对多关系转化为多对对多如果各个同事的间本来关联就很清晰(没有交错关联)或这种关联并不复杂没有必要应用中介者

  l         在实际应用过程中中介者做控制并不会向本例那样简单它可能包含很多处理逻辑如果还伴随着需求改变中介者角色可能会越来越难维护此时可以考虑对中介者角色或处理行为应用其它些设计模式

  系列文章:

  无废话C#设计模式的:开篇

  无废话C#设计模式的 2:Singleton

  无废话C#设计模式的 3:Abstract Factory

  无废话C#设计模式的 4:Factory Method

  无废话C#设计模式的 5:Prototype

  无废话C#设计模式的 6:Builder

  无废话C#设计模式的 7:Adapter

  无废话C#设计模式的 8:Facade

  无废话C#设计模式的 9:Proxy

  无废话C#设计模式的十:Flyweight

  无废话C#设计模式的十:Composite

  无废话C#设计模式的十 2:Bridge

  无废话C#设计模式的十 3:Decorator



  无废话C#设计模式的十 4:Template Method

  无废话C#设计模式的十 5:Strategy

  无废话C#设计模式的十 6:State

  无废话C#设计模式的十 7:Chain Of Resp

  无废话C#设计模式的十 8:Command

  无废话C#设计模式的十 9:Observer

  无废话C#设计模式的 2十:Visitor

  无废话C#设计模式的 2十 2:整理总结(针对GOF23)



标签:
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: