一、定义
中介者模式:用一个中介对象来封装一系列的对象交互。中介者使对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
解释:通俗来讲,有多个对象,它们相互之间有交互。现在为了降低它们的耦合度,提供一个中介者,相当于第三方,各个对象都通过第三方来进行相互间的逻辑操作。
二、UML类图及基本代码
基本代码:
abstract class Mediator { public abstract void Send(string message, Colleague colleague); } class ConcreteMediator : Mediator { private ConcreteColleage1 colleague1; private ConcreteColleage2 colleague2; public ConcreteColleage1 Colleague1 { set { colleague1 = value; } } public ConcreteColleage2 Colleague2 { set { colleague2 = value; } } public override void Send(string message, Colleague colleague) { if (colleague == colleague1) { colleague2.Receive(message); } else { colleague1.Receive(message); } } } abstract class Colleague { protected Mediator mediator; public Colleague(Mediator mediator) { this.mediator = mediator; } } class ConcreteColleage1 : Colleague { public ConcreteColleage1(Mediator mediator) : base(mediator) { } public void Send(string message) { mediator.Send(message, this); } public void Receive(string message) { Console.WriteLine("同事1得到信息:" + message); } } class ConcreteColleage2 : Colleague { public ConcreteColleage2(Mediator mediator) : base(mediator) { } public void Send(string message) { mediator.Send(message, this); } public void Receive(string message) { Console.WriteLine("同事2得到信息:" + message); } }
客户端调用及其结果:
ConcreteMediator mediator = new ConcreteMediator(); ConcreteColleage1 c1 = new ConcreteColleage1(mediator); ConcreteColleage2 c2 = new ConcreteColleage2(mediator); mediator.Colleague1 = c1; mediator.Colleague2 = c2; c1.Send("吃饭了吗?"); c2.Send("还没有,你打算请客?");
三、具体实例
A和B博弈,A赢则B会输,反之亦然。假设A和B开始时都要20块钱,基本代码如下:
首先构造抽象中介者类和具体中介者类:
public abstract class AbstractMediator { public abstract void AWin(int count); public abstract void BWin(int count); } public class MediatorPater : AbstractMediator { private ParterA a; private ParterB b; public ParterA A { set { a = value; } } public ParterB B { set { b = value; } } public override void AWin(int count) { a.MoneyCount += count; b.MoneyCount -= count; } public override void BWin(int count) { b.MoneyCount += count; a.MoneyCount -= count; } }
接着编写抽象对弈者,构造具体的对弈者A和B:
public abstract class AbstractCardPartner { public int MoneyCount { get; set; } public AbstractCardPartner() { MoneyCount = 0; } public abstract void ChangeCount(int count, AbstractMediator mediator); } public class ParterA : AbstractCardPartner { public override void ChangeCount(int Count, AbstractMediator mediator) { mediator.AWin(Count); } } public class ParterB : AbstractCardPartner { public override void ChangeCount(int Count, AbstractMediator mediator) { mediator.BWin(Count); } }
客户端调用代码及其结果:
MediatorPater mediator = new MediatorPater(); ParterA partA = new ParterA(); ParterB partB = new ParterB(); mediator.A = partA; mediator.B = partB; partA.MoneyCount = 20; partB.MoneyCount = 20; partA.ChangeCount(7, mediator); Console.WriteLine("A 现在的钱是:{0}", partA.MoneyCount); Console.WriteLine("B 现在的钱是:{0}", partB.MoneyCount); partB.ChangeCount(11, mediator); Console.WriteLine("A 现在的钱是:{0}", partA.MoneyCount); Console.WriteLine("B 现在的钱是:{0}", partB.MoneyCount);
四、优缺点及其适用场景
优点:
1)将各个对象类解耦,同时简化对象之间的关系,使系统变为松耦合。
2)系统更加灵活,各个对象独立而易于复用。
缺点:
1)中介者模式中,中介者承担了较大的责任,一旦中介者出现问题,整个系统都会受到较大的影响。
2)新增一个对象类,需要修改抽象中介者和具体中介者类。
适用场景:
中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合,及想定制一个分布在多个类中的行为,而又不想生成太多的子类的场合。
补充:
再次重温中介者模式,发现该模式好像有些鸡肋,发现上面展示的中介者的基本代码的耦合度太高了,于是网上搜索其它关于中介者的实例,希望能从那些实例中得到一些启发。而事实是确实找到一个比较好的实例,实例如下:
抽象对象:
abstract class Colleague { private string name; private string content; public Colleague(string name) { this.name = name; } public void SetContent(string content) { this.content = content; } public string GetContent() { return this.content; } public abstract void Talk(); }
添加几个具体的对象:
class ConcreteColleagueMonitor : Colleague { public ConcreteColleagueMonitor (string name):base(name){} public override void Talk() { Console.WriteLine("班长说:" + GetContent()); } } class ConcreteColleague1 : Colleague { public ConcreteColleague1(string name) : base(name) { } public override void Talk() { Console.WriteLine("同学1说:" + GetContent()); } } class ConcreteColleague2 : Colleague { public ConcreteColleague2 (string name):base(name){} public override void Talk() { Console.WriteLine("同学2说:" + GetContent()); } }
抽象中介者:
abstract class Mediator { public IList<Colleague> Colleagues = new List<Colleague>(); public abstract void Notify(Colleague colleague); public abstract void Chart(Colleague colleague1, Colleague colleague2); public void AddColleague(Colleague colleague) { Colleagues.Add(colleague); } }
具体的中介者qq群:
class QQMediator : Mediator { public override void Notify(Colleague colleague) { colleague.Talk(); foreach (Colleague c in Colleagues) { if (c != colleague) c.Talk(); } } public override void Chart(Colleague colleague1, Colleague colleague2) { colleague1.Talk(); colleague2.Talk(); } }
客户端调用代码:
QQMediator qq = new QQMediator(); ConcreteColleagueMonitor monitor = new ConcreteColleagueMonitor("班长"); ConcreteColleague1 colleague1 = new ConcreteColleague1("同学1"); ConcreteColleague2 colleague2 = new ConcreteColleague2("同学2"); Console.WriteLine("班长发通知场景:"); qq.AddColleague(monitor); qq.AddColleague(colleague1); qq.AddColleague(colleague2); monitor.SetContent("今天中午聚餐,收到回复"); colleague1.SetContent("没问题"); colleague2.SetContent("可以,但是会晚到"); qq.Notify(monitor); Console.WriteLine("......................................................."); Console.WriteLine("两个同学(班长、同学2)私下交流:"); monitor.SetContent("明天一块去逛街,怎么样?"); colleague2.SetContent("可以呀,早就想去了。"); qq.Chart(monitor, colleague2);
结果显示如下:
实例到此完毕。
联想到以前看过的模板模式,从上面的实例生成具体的对象,在此处中介者模式是不是可以嵌套模板模式呢,下次看到此处时进行再次补充。
引用: