Unity 3D Framework Designing(2)——使用中介者模式解耦ViewModel之间通信
当你开发一个客户端应用程序的时候,往往一个单页会包含很多子模块,在不同的平台下,这些子模块又被叫成子View(视图),或者子Component(组件)。越是复杂的页面,被切割出来的子模块就越多,子模块越多,彼此之间需要同步的数据和状态就越频繁,即易产生耦合。那么如何保证在复杂业务情况下,各个子模块之间可以随意通信并保持弱耦合关系,这正是本文所讨论的。
耦合的产生
试想一下,你有这样一下需求,点击 View A中的按钮,View B也需要做出相应的改变。

这不是很简单吗。脑海里迅速出现两种解决方案:
1.View A 主动通知View B做出更新,也就是View A依赖 View B
void Notify()
{
ViewB.Update(color);
}
2.View B监听View A的ColorChanged事件,主动拉取数据并更新,即ViewB 依赖View A
ViewA.OnColorPropertyValueChanged+=(color)=>{
Update(color);**
}
这两种实现毫无疑问是没问题的,至少从结果上来看是正确的。但试想一下,在一个复杂的客户端单页应用程序,这种紧耦合关系会导致程序的复杂度陡然上升。每个View/ViewModel依赖其余对象,而本身又被其他View/ViewModel强引用。这显然不是好的实践方式。
还记得我在上一篇文章的对于MVVM的描述吗?
MVVM的核心思想就是解耦,View与ViewModel应该感受不到彼此的存在。ViewModel与ViewModel之间也应该感受不到彼此的存在。
中介者模式的引入
那么如何消除这种紧耦合关系呢?交给中介者设计模式来解决吧。
我们需要添加一个中介者,每个ViewModel Publisher对象都会在自己状态改变时,告诉中介者。每个ViewModel Subscribers 都需要告诉中介者请求来时进行怎样的响应。

在没有中介者之前对象之间都需要彼此认识,互相引用,是一种强耦合关系。有了中介者之后,彻底解耦。
那么现在就需要定义一个中介者,称为MessageAggregator。因为由它来转发消息,所以核心是一个字典,保存了所有需要被转发的消息。它的Key为消息的唯一Id,Value代表一个对该Message的处理程序。
public delegate void MessageHandler<T>(object sender, MessageArgs<T> args);
public class MessageAggregator<T>
{
private readonly Dictionary<string, MessageHandler<T>> _messages = new Dictionary<string, MessageHandler<T>>();
public static readonly MessageAggregator<T> Instance=new MessageAggregator<T>();
private MessageAggregator()
{
}
public void Subscribe(string name, MessageHandler<T> handler)
{
if (!_messages.ContainsKey(name))
{
_messages.Add(name, handler);
}
else
{
_messages[name] += handler;
}
}
public void Publish(string name, object sender, MessageArgs<T> args)
{
if (_messages.ContainsKey(name) && _messages[name] != null)
{
//转发
_messages[name](sender, args);
}
}
}
解耦ViewModel与ViewModel###
通过中介者MessageAggregator对象,ViewModelB Subscribe一个对消息来时的处理函数:
MessageAggregator<object>.Instance.Subscribe("ColorChanged",ToggleHandler);
ViewModel A在自己状态改变时,Pulish状态改变的消息给中介者:
MessageAggregator<object>.Instance.Publish("ColorChanged", this,new MessageArgs<object>("Red"));

小结###
中介者模式常常用来协调相关的GUI组件,可以让对象之间传递的消息变得简单。但如果设计不当,中介者本身会变得过于复杂。
源代码托管在Github上,点击此了解
Unity 3D Framework Designing(2)——使用中介者模式解耦ViewModel之间通信的更多相关文章
- Unity应用架构设计(2)——使用中介者模式解耦ViewModel之间通信
当你开发一个客户端应用程序的时候,往往一个单页会包含很多子模块,在不同的平台下,这些子模块又被叫成子View(视图),或者子Component(组件).越是复杂的页面,被切割出来的子模块就越多,子模块 ...
- Unity 3D Framework Designing(3)——构建View和ViewModel的生命周期
> 对于一个View而言,本质上是一个MonoBehaviour.它本身就具备生命周期这个概念,比如,Awake,Start,Update,OnDestory等.这些是非常好的方法,可以让开发者 ...
- Unity 3D Framework Designing(1)—— MVVM 模式的设计和实施(Part 2)
MVVM回顾 经过上一篇文章的介绍,相信你对 MVVM的设计思想有所了解.MVVM的核心思想就是解耦,View与ViewModel应该感受不到彼此的存在.View只关心怎样渲染,而ViewModel只 ...
- Unity 3D Framework Designing(1)—— MVVM 模式的设计和实施(Part 1)
初识 MVVM 谈起 MVVM 设计模式,可能第一映像你会想到 WPF/Sliverlight,他们提供了的数据绑定(Data Binding),命令(Command)等功能,这让 MVVM 模式得到 ...
- Unity 3D Framework Designing(4)——设计可复用的SubView和SubViewModel(Part 1)
『可复用』这个词相信大家都熟悉,通过『可复用』的组件,可以大大提高软件开发效率. 值得注意的事,当我们设计一个可复用的面向对象组件时,需要保证其独立性,也就是我们熟知的『高内聚,低耦合』原则. 组件化 ...
- Unity 3D Framework Designing(6)——设计动态数据集合ObservableList
什么是 『动态数据集合』 ?简而言之,就是当集合添加.删除项目或者重置时,能提供一种通知机制,告诉UI动态更新界面.有经验的程序员脑海里迸出的第一个词就是 ObservableCollection.没 ...
- Unity 3D Framework Designing(7)——IoC工厂理念先行
一谈到 『IoC』,有经验的程序员马上会联想到控制反转,将创建对象的责任反转给工厂.IoC是依赖注入 『DI』 的核心,大名鼎鼎的Spring框架就是一个非常卓越的的控制反转.依赖注入框架.遗憾的是, ...
- Unity 3D Framework Designing(9)——构建统一的 Repository
谈到 『Repository』 仓储模式,第一映像就是封装了对数据的访问和持久化.Repository 模式的理念核心是定义了一个规范,即接口『Interface』,在这个规范里面定义了访问以及持久化 ...
- Unity 3D Framework Designing(4)——设计可复用的SubView和SubViewModel(Part 2)
在我们设计和开发应用程序时,经常要用到控件.比如开发一个客户端WinForm应用程序时,微软就为我们提供了若干控件,这些控件为我们提供了可被定制的属性和事件.属性可以更改它的外观,比如背景色,标题等, ...
随机推荐
- jquery在Asp.net下实现ajax
前台代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AjaxTest ...
- PHP 数组处理
一:PHP 定义数组: PHP 代码 不能再 空的位置 打字 会报错 定义数组 方式1 $cars=array("Volvo","BMW","T ...
- this的相关介绍与用法
当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是this.因此,this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现this,并 ...
- webForm系列 前端框架快速引用
Html的确定就是不能重用,MVC可以在_Layout.cshtml中将每个页面都需要的js和css文件(如jq,bootstrap等)都引用进去,webform就麻烦一点. webForm需要给所以 ...
- django源码简析——后台程序入口
这一年一直在用云笔记,平时记录一些tips或者问题很方便,所以也就不再用博客进行记录,还是想把最近学习到的一些东西和大家作以分享,也能够对自己做一个总结.工作中主要基于django框架,进行项目的开发 ...
- NSRunLoop原理详解——不再有盲点
编程最怕的就是有盲点,不确定,而runloop官网对其提及的又很少:那么看完这篇应该使你有底气很多~ RunLoop整体介绍 An event-processing loop, during whic ...
- 新手向--git版本控制器
body { width: 70%; border: 1px solid #ddd; outline: 1300px solid #fff; margin: 16px auto } body .mar ...
- Ajax封装函数笔记
Ajax封装函数: function ajax(method, url, data, success) { //打开浏览器 //1.创建一个ajax对象 var xhr = null; try { x ...
- JS实例——间歇循环滚动
间歇滚动:滚动一行后,延迟2秒后继续滚动 具体实现代码如下: <!doctype html> <html lang="en"> <head> & ...
- 2017-3-2 C#基础 结构体
1. 结构体:用户自定义类型定义位置:定义在Main函数的外面,类的里面 定义格式:struct 自定义名字{ public 数据类型 名字; public 数据类型 名字; ... ...} 声明实 ...