意圖
用一個中介對象封裝一系列的對象交互毕荐,中介者使各對象不需要顯示地相互引用郁惜,從而使其耦合松散涡上,而且可以獨立地改變它們之間的交互浑玛。
結構
中介者結構圖
動機
面向對象設計鼓勵將行為分布到各個對象中绍申,以提高這些行為的可復用性。但是顾彰,采用這種分割方式的系統(tǒng)极阅,也可能會引起對象之間的相互連接(直接引用)激增,反而降低了它們的可復用性(依賴與耦合過高)涨享。
中介者模式通過將集體行為封裝到一個獨立的中介者對象筋搏,由中介者負責控制和協調對象間的交互,使對象間不再相互顯式引用厕隧,提高可復用性奔脐。
適用性
- 一組對象以定義良好但是復雜的方式進行通信。產生的相互依賴關系結構混亂且難以理解吁讨;
- 一個對象引用其他很多對象并且直接與這些對象通信,導致難以復用該對象髓迎;
- 想定制一個分布在多個類中的行為,而又不想生成太多的子類建丧。
優(yōu)缺點
- 中介者把各個對象組織在一起竖般,負責協調它們之間的業(yè)務邏輯。如果業(yè)務發(fā)生變化茶鹃,只需要生成Mediator子類即可涣雕,這樣各個Colleague類可被重用;
- 中介者有利于各個Colleague之間的松耦合闭翩,可以獨立地改變和復用Mediator及Colleague挣郭;
- 中介者抽象了對象間的協作行為,使關注點從對象本身的行為轉移到對象間的交互疗韵。有助于我們弄清楚一個系統(tǒng)中的對象是如何交互的兑障。
- 中介者的集中化控制的特點,使得交互的復雜性變成了中介者的復雜性蕉汪。
其他
- Mediator 與 Colleague 之間的通訊方式:
- 使用觀察者模式:Colleague類為Subject流译,Mediator類為Observer;
- 在Mediator中定義一個特殊的通知接口者疤,各Colleague在通知時直接調用該接口福澡。
示例
模擬一個圖形用戶界面,該界面有2個窗體控件:下拉列表框(ListBox)和文本框(TextBox)驹马。當下拉列表框某一項被選中時革砸,文本框的內容將自動更新除秀。
實現(C#)
圖形界面結構圖
以及它們之間的交互時序圖:
圖形用戶界面交互時序圖
using System;
public abstract class Mediator
{
public abstract void CreateWidgets();
public abstract void WidgetChanged(Widget widget);
}
public class DialogMediator : Mediator
{
private ListBox list;
private TextBox field;
public override void CreateWidgets()
{
list = new ListBox(this);
field = new TextBox(this);
}
public override void WidgetChanged(Widget widget)
{
if(widget is ListBox)
{
string text = list.GetSelectedItem();
field.SetText(text);
}
// else if(widget is TextBox) ...
}
public ListBox ListBox { get { return this.list; }}
public TextBox Field { get { return this.field; }}
}
// 圖形窗體的基類
public abstract class Widget
{
private readonly Mediator mediator;
protected Widget(Mediator mediator)
{
this.mediator = mediator;
}
public void Changed()
{
this.mediator.WidgetChanged(this);
}
}
// 列表框控件
public class ListBox : Widget
{
private readonly string[] items;
private int selectedIndex = -1;
public ListBox(Mediator mediator) : base(mediator)
{
items = new [] {"1.華為", "2.小米", "3.OPPO", "4.三星", "5.蘋果"};
}
public void SetSelectedItem(int index)
{
this.selectedIndex = index;
// 引發(fā)一個事件。
this.Changed();
}
public string GetSelectedItem()
{
if(this.selectedIndex >= 0 && this.selectedIndex < items.Length)
{
return items[this.selectedIndex];
}
else
{
return "未選中";
}
}
}
// 文本框控件
public class TextBox : Widget
{
private string text;
public TextBox(Mediator mediator) : base(mediator) {}
public void SetText(string text)
{
this.text = text;
}
public string GetText()
{
return this.text;
}
}
// 測試
public class App
{
public static void Main(string[] args)
{
DialogMediator dialog = new DialogMediator();
//1. 創(chuàng)建各個控件
dialog.CreateWidgets();
//2.模擬選中某個列表項動作
dialog.ListBox.SetSelectedItem(2);
Console.WriteLine(dialog.Field.GetText());
//2.模擬選中某個列表項動作
dialog.ListBox.SetSelectedItem(4);
Console.WriteLine(dialog.Field.GetText());
}
}
// 控制臺輸出:
// 3.OPPO
// 5.蘋果