耦合的产生
试想一下,你有这样一下需求,点击 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的描述吗?
中介者模式的引入
那么如何消除这种紧耦合关系呢?交给中介者设计模式来解决吧。
在没有中介者之前对象之间都需要彼此认识,互相引用,是一种强耦合关系。有了中介者之后,彻底解耦。
那么现在就需要定义一个中介者,称为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上,点击此了解