一個軟件系統中往往包含了很多的類,這些類之間會存在互相的調用,隨着系統的升級、功能的擴展,這些相互調用關係會變得非常複雜,,大量的相互連接使得這樣一個類型系統不太可能在沒有其他類支持的情況下獨立完成工作,久而久之這些類將變得像一個不可分割的整體,內部有着錯綜複雜的關聯。這會導致後期維護特別困難,對系統或模塊的任何較大的變動都可能造成無法預知的問題。
中介者模式
中介者模式可以解決這種問題。它通過提供一箇中介類,來處理不同類之間的通信,這樣可以降低多個類之間的通信複雜度,使代碼更易於維護。中介者模式屬於行爲型模式。通過應用Mediator模式,可以將類與類之間的多對多的關係轉化成一對多的關係,從而降低了類之間的耦合。
GOF對中介者模式描述爲:
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently..
— Design Patterns : Elements of Reusable Object-Oriented Software
UML類圖:
代碼實現
public interface IMediator<T>
{
void Operation();
void Register(IColleague<T> provider, params IColleague<T>[] consumers);
}
public interface IColleague<T>
{
T Data { get; set; }
IMediator<T> Mediator { get; set; }
}
public abstract class ColleagueBase<T> : IColleague<T>
{
public virtual T Data { get; set; }
private IMediator<T> mediator;
public virtual IMediator<T> Mediator
{
get
{
return mediator;
}
set
{
mediator = value;
}
}
}
public class Mediator<T> : IMediator<T>
{
private IColleague<T> provider;
private IList<IColleague<T>> consumers;
public void Operation()
{
if (provider != null && consumers != null && consumers.Count > 0)
{
foreach (var item in consumers)
{
item.Data = provider.Data;
}
}
}
public void Register(IColleague<T> provider, params IColleague<T>[] consumers)
{
this.provider = provider;
if (consumers != null && consumers.Length > 0)
{
this.consumers = new List<IColleague<T>>(consumers);
}
}
}
public class ConcreteColleagueA : ColleagueBase<int>
{
public override int Data
{
get => base.Data;
set
{
base.Data = value;
base.Mediator.Operation();
}
}
}
public class ConcreteColleagueB : ColleagueBase<int>
{
}
public class ConcreteColleagueC : ColleagueBase<int>
{
}
調用端:
public class Test
{
public static void Entry()
{
Mediator<int> mA2BC = new Mediator<int>();
ConcreteColleagueA a = new ConcreteColleagueA();
ConcreteColleagueB b = new ConcreteColleagueB();
ConcreteColleagueC c = new ConcreteColleagueC();
a.Mediator = b.Mediator = c.Mediator = mA2BC;
mA2BC.Register(a, b, c);
a.Data = 20;
Console.WriteLine($"a:{a.Data},b:{b.Data}, c:{c.Data}"); //a:20,b:20,c:20
mA2BC.Register(a, b);
a.Data = 30;
Console.WriteLine($"a:{a.Data},b:{b.Data}, c:{c.Data}"); //a:30,b:30,c:20
}
}
適用場景
- 系統中對象之間存在比較複雜的引用關係,導致他們之間的依賴關係結構混亂而且難以複用該對象。
- 想通過一箇中間類來封裝多個類中的行爲,而又不想生成太多的子類。
優缺點
優點
- 降低了系統類的複雜度,將一對多轉化成了一對一,只需要與中介者交互
- 中介者模式使得對象之間不需要顯式地相互引用,從而使得系統或模塊內部相互解耦。
- 符合迪米特原則
缺點
由於中介者對象封裝了各個類之間的交互,會導致中介者類本身的複雜性上升,會有一定的維護成本
參考書籍:
王翔著 《設計模式——基於C#的工程化實現及擴展》