當你開發一個客戶端應用程序的時候,往往一個單頁會包含很多子模塊,在不同的平台下,這些子模塊又被叫成子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上,點擊此了解