`
love_jun1314
  • 浏览: 2842 次
文章分类
社区版块
存档分类
最新评论

MVC结合Mediator模式的运用

    博客分类:
  • Flex
 
阅读更多
 Mediator模式有一种本事,就是可以让本身需要互相协作的对方,可以不用知道彼此,而把两者之间的联系,转交给Mediator来处理。换句话说,Mediator模式解除了需要互相协调的对象之间的依赖。这也是Mediator(调停者)模式名字的由来。一个颇为形象的例子是***。

  进入***的用户总是要彼此通信的,这些对象如果直接进行交互,就会彼此连接,最后织成一张纷繁复杂的大网。要分清彼此之间的关系,真可以说是“剪不断理还乱”了。所以,引入一个***对象来管理用户间的交流,就势成必然。

  Mediator模式与Facade模式都是管理复杂对象的行家里手,不过二者在运用上还是有本质的不同。Facade是门面,通过它隔断了客户端与复杂对象之间的直接关系。Mediator是仲裁者,哪里出现纠纷哪里就有它的身影。

  Facade对象对于客户端来说是可见的,而隐藏了复杂对象;Mediator对象对于客户端来说则是隐藏的,客户端直接调用复杂对象,而复杂对象之间的关系,则转交给了Mediator。

  MVC模式则是职责分离的典范,就好似三权分立一般,各司其职。Model负责提供数据,View则负责显示数据,Controller则负责控制Model与View之间的交互,封装了领域逻辑。这样的职责分离形式,能够有效地解除数据、业务逻辑与UI界面之间的耦合关系。但是,在MVC模式中,由于业务逻辑的问题,很有可能在Controller之间还需要进行交互。这种交互一旦增多,就可能出现在一个Controller中出现不同的Controller,导致代码出现分散,形成霰弹式修改的坏味道。

  Marlon在其博客上发表了一篇文章,有效地将MVC模式与Mediator模式两者结合,创造出一种称之为MVC+M的模式,有效地解决了Controller对象之间相互依赖的问题。Marlon实现了一个文件浏览器来展示这一模式。运行程序,当我们点击左边的目录树时,在右边就会显示当前目录下的所有文件。UI如图所示:



左边视图对应的控制对象为DirectorySelectorController,而右边视图对应的则为FileSelectorController对象。Marlon统一定义了一个接口IColleague,作为Mediator模式中参与者的抽象接口,并让相关的Controller实现它。类图如下所示:



每个Controller对象所接收的Mediator对象都是相同的,因为Mediator对象作为BaseController基类的属性存在,并利用了Singleton模式,保证了Mediator对象只能存在一个:


public abstract class BaseController : INotifyPropertyChanged, IColleague

{

    static Mediator mediatorInstance = new Mediator();



    public Mediator Mediator { get; private set; }



    public BaseController()
    {

        //set the mediator to be the same one for every controller.

        Mediator = mediatorInstance;

    }


     //rest of implementation

}



在子类的构造函数中,通过调用Mediator对象的Register方法,建立了消息与Controller对象之间的映射关系。以FileSelectorController类为例:


public FileSelectorController()

{

    Mediator.Register(this, new[]

    {

        Messages.DirectorySelectedChanged

    });

}

Mediator类完成Controller对象之间的协调,其定义如下:


public class Mediator

{

    MultiDictionary<string, IColleague> internalList

        = new MultiDictionary<string, IColleague>();




    public void Register(IColleague colleague, IEnumerable<string> messages)

    {

        foreach (string message in messages)

            internalList.AddValue(message, colleague);

    }



    public void NotifyColleagues(string message, object args)
    {

        if (internalList.ContainsKey(message))

        {

            //forward the message to all listeners

            foreach (IColleague colleague in internalList[message])

                colleague.MessageNotification(message, args);

        }

    }

}

Register()方法会将消息与Controller对象的映射注册到内部字典internalList中。而NotifyColleagues()方法则会遍历整个internalList,然后执行Controller对象(体现为IColleague类型)的MessageNotification()方法。通过MessageNotification()方法,每个Controller对象根据传输的消息字符串,做出相应的响应操作。例如在FileSelectorController类中,就是根据Message的值,执行装载文件的业务逻辑:


public override void MessageNotification(string message, object args)

{

    switch (message)

    {

        case Messages.DirectorySelectedChanged:

            //load all files for the directory specified

            LoadFiles((DirectoryDisplayItem)args);

            break;

    }

}

如果没有引入Mediator模式,由于需要在点击目录时显示当前目录的文件,因此在DirectorySelectorController类的ItemSelected事件中,必须调用FileSelectorController对象获取文件信息,然后通过对应视图显示这些文件信息。这就导致了DirectorySelectorController和FileSelectorController之间的依赖。现在,在DirectorySelectorController的ItemSelected事件中,就可以通过Mediator来实现文件信息的读取与显示:


//event handler for the selecting changed

void ItemSelected(object sender, RoutedEventArgs e)

{

    TreeView treeView = (TreeView)e.OriginalSource;

    //Send a message that an item is selected and pass the object selected

    Mediator.NotifyColleagues(Messages.DirectorySelectedChanged, treeView.SelectedItem);

}

Marlon实现的MVC+M模式有效地解除了Controller对象之间的耦合关系,其中,他引入了IColleague接口对Controller的相关方法进行了抽象。不过,这样的接口并非必须,正如我在《Strategy模式与Delegate委托》一文中提到的接口与委托之间的关系,我们完全可以用委托来代替IColleague接口的定义,使整个结构变得更加的灵活。由于引入了委托与消息对象的映射关系,因此在Controller类的MessageNotification()方法中,不再需要用switch语句来判断消息的值,而是直接根据映射关系,调用委托对象所指代的方法逻辑。Mediator类可以修改为:


public class Mediator

{

    IDictionary<string,Action<object>> m_List = new Dictionary<string,Action<object>>();



    public void Register(string message,Action<object> callback)

    {

        m_List.Add(message,callback);

    }



    public void NotifyColleagues(string message, object args)

    {

        if (m_List.ContainsKey(message))

        {

            m_List[message](args);

        }

    }

}

与之对应的,FileSelectorController可以修改为:


public FileSelectorController()

{

    Mediator.Register(Messages.DirectorySelectedChanged,

        (obj) =>

        {

            LoadFiles((DirectoryDisplayItem)obj);

        });

}

至于最初定义在Controller类的MessageNotification()方法,则被匿名函数所代替,已经不再需要了
分享到:
评论

相关推荐

    初探PureMVC:使用PHP+MySQL+Flex结合PureMVC框架做了个Flex留言本

    标题中的“初探PureMVC:使用PHP+MySQL+Flex结合PureMVC框架做了个Flex留言本”揭示了本文将探讨如何使用PureMVC框架,结合PHP后端和MySQL数据库,构建一个基于Flex的前端留言本应用。PureMVC是一个轻量级、可扩展的...

    MVC模式 MVC组件类型的关系和功能

    MVC模式常常与其他设计模式相结合,如: - 观察者模式(Observer Pattern):用于在模型和视图之间建立双向绑定,模型变化时通知视图更新。 - 策略模式(Strategy Pattern):控制器可以根据不同情况选择不同的处理...

    基于PureMVC框架实现的Qt的一个例子

    通过阅读和分析PureMVC_Qt_example中的代码,你可以深入理解如何在C++环境中运用PureMVC,从而提升自己的软件开发技能。此外,还可以尝试扩展这个例子,添加更多功能,以加深对PureMVC和Qt集成的理解。

    C#面向对象设计模式纵横谈(17):(行为型模式) Mediator 中介者模式

    标题和描述均提到了"C#面向对象设计模式纵横谈(17):(行为型模式) Mediator 中介者模式",这明确指向了一个特定的设计模式——中介者模式(Mediator Pattern),并且是在C#语言环境下的应用。下面将详细阐述这一设计...

    pureMVC Demo C#

    纯MVC(PureMVC)是一个轻量级的框架,主要设计用于构建具有模型-视图-控制器(Model-View-...通过分析和实践这个Demo,开发者能够更好地理解MVC模式,以及如何在C#项目中运用PureMVC进行高效、整洁的代码组织。

    flex pure mvc框架

    Flex是用于构建富互联网应用(RIA)的开发平台,而Pure MVC则是帮助开发者组织和管理代码结构的框架,两者结合能够提升Flex应用的可维护性和可扩展性。 在Flex Pure MVC框架中,主要包含三个核心组件:模型(Model...

    设计模式:可复用面向对象软件的基础--详细书签版

     本书结合设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好、表达清楚的软件设计模式,这些模式在实用环境下特别...

    C#設計模式

    如策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、责任链模式(Chain of Responsibility)、命令模式(...状态模式(State)、访问者模式(Visitor)和中介者模式(Mediator)...

    puremvc-lua

    3. **文档**:可能有 README 文件或其他形式的文档,解释框架的安装、配置和使用方法,以及如何将 PureMVC 结合到现有的 Lua 项目中。 4. **测试**:可能包含测试用例,用来验证框架的功能和性能,确保其正确性和...

    BasePureMVC.zip

    在PureMVC中,视图通过Mediator类来实现,Mediator作为视图组件和控制器之间的中介,处理视图组件的事件并转发给控制器。在Egret中,这可能涉及精灵、舞台元素的更新和动画效果的处理。 3. **控制器(Controller)*...

    设计模式整理

    - 中介者模式(Mediator):用一个中介对象封装一系列的对象的交互,使得这些对象不需要显示地相互引用,降低耦合度。 - 备忘录模式(Memento):在不破坏封装的前提下,捕获一个对象的内部状态,并在需要时将此状态...

    C++11全套设计模式-23种指针的用法(a full DesignPattern -DesignPattern.zip

    22. **中介者模式(Mediator)**:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。C++11的事件驱动编程可以实现这一模式。 23....

    WOZLLA.PureMVC.js:WOZLLA.js 的 PureMVC 插件

    总之,WOZLLA.PureMVC.js结合了WOZLLA.js的2D游戏开发能力与PureMVC的架构优势,为JavaScript游戏开发者提供了一种更有序、更易于维护的开发方式。通过深入理解和运用这个插件,开发者可以创建出更加高效、结构化的...

    head first design patterns 英文原版高清

    第12章探讨了如何将设计模式结合起来形成复合设计模式,并以MVC(模型-视图-控制器)模式为例进行了说明。MVC模式是将一个应用程序分为三个核心部件:模型、视图和控制器。 第13章关注于如何进一步学习设计模式,...

    Head First Design Patterns

    - **第十二章**:介绍如何将两个或多个设计模式结合使用形成新的设计模式,这种复合设计模式的例子之一就是著名的MVC(Model-View-Controller)模式。 - **第十三章**:探讨如何进一步学习设计模式,以及如何发现新...

    java经典面试题6

    - **中介者模式(Mediator)**:用一个中介对象来封装一系列的对象交互。 - **备忘录模式(Memento)**:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 - **观察者模式...

Global site tag (gtag.js) - Google Analytics