提供一个中介对象出来,用于封装一系列对象的交互,从而使各对象不需要直接交互,进一步降低了对象间的耦合度。这是一种行为型设计模式。
由此可见,中介者模式主要解决的是对象间所存在的大量关系,我们都知道,对象间一旦关联紧密,必然会导致系统的复杂性增加,一旦某个对象有所修改,其关联对象也有可能会有跟着更改,这自然不是我们所希望的。有些朋友可能会说,如果交互很多,是不是可以将对象合并,从某种角度上来说,我们可以考虑对象合并。但是,我们并不能这样去做,因为对象存在的层级可能是不同的,有些是处理数据交互的,有些是处理业务级的,合并起来会导致系统层次不明,引入更大的风险。
在现实生活中,中介者更多的体现为调度平台或者房产中介,再或者就是红娘了。我们以红娘为例,
程序员找个女朋友实在是太难,而且时间也不多,圈子也不大,一个一个去认识,鬼知道哪一个要找对象的,耗费精力不说,尼玛,还少敲了好几段代码。所以,一般通过红娘会更方便一点,会使得我们的目的更加明确,就是找对象,筛选、信息收集、匹配的事情交给红娘做就好了。毕竟红娘可是掌握着很多女孩子的信息及其择偶要求的,程序员过去把信息或者要求填写一下即可,红娘帮你匹配合适的女孩子,一旦有较高的匹配度,就可以约会见见了,说不准很快就成了,这样代码没少敲,对象也不耽误找,是不是很爽……
以上,我们可以发现,在中介者模式里面,中介者承担的职能主要包括:
UML描述的是程序员相亲的例子
通过以上UML图,我们可以知道,中介者模式主要有以下几个角色 Mediator: 抽象中介者。定义了同事对象与中介者对象进行交互的接口。 ConcreteMediator: 具体中介者,实现抽象中介者的方法。 Colleague: 抽象同事类。 ConcreteColleague: 具体同事类。每个具体同事类都只需要知道自己的行为即可,他们是直接与中介者打交道的类。
接下来我们以程序员找对象为例,这里的中介者就是程序员与妹子之间协调的红娘了,来看看如何通过代码编写
核心逻辑代码:
1: /// <summary> 2: /// 抽象中介者 3: /// </summary> 4: public abstract class Mediator 5: { 6: /// <summary> 7: /// 相亲 8: /// </summary> 9: public abstract void BlindDate(Colleague colleague, string msg); 10: } 11: 12: /// <summary> 13: /// 抽象同事类 14: /// </summary> 15: public abstract class Colleague 16: { 17: protected Mediator mediator; 18: protected string msg; 19: 20: public Colleague(Mediator mediator, string msg) 21: { 22: this.mediator = mediator; 23: this.msg = msg; 24: } 25: 26: public abstract void Communication(string msg); 27: } 28: 29: /// <summary> 30: /// 媒婆或者说是红娘 31: /// </summary> 32: /// <seealso cref="ConsoleApp2.Colleague" /> 33: public class Matchmaker : Colleague 34: { 35: public Matchmaker(Mediator mediator, string msg) : base(mediator, msg) 36: { 37: } 38: 39: public void BlindDate() 40: { 41: this.mediator.BlindDate(this, this.msg); 42: } 43: 44: public override void Communication(string msg) 45: { 46: Console.WriteLine(this.msg + ":" + msg); 47: } 48: } 49: 50: /// <summary> 51: /// 相亲者 52: /// </summary> 53: /// <seealso cref="ConsoleApp2.Colleague" /> 54: public class Programmer : Colleague 55: { 56: public Programmer(Mediator mediator, string msg) : base(mediator, msg) 57: { 58: } 59: 60: public void BlindDate() 61: { 62: this.mediator.BlindDate(this, this.msg); 63: } 64: 65: public override void Communication(string msg) 66: { 67: Console.WriteLine(this.msg + ":" + msg); 68: } 69: } 70: 71: /// <summary> 72: /// 这里就是中介机构了,暂且叫做结婚吧,作为一个中介结构,里面的信息是完全的 73: /// </summary> 74: /// <seealso cref="ConsoleApp2.Mediator" /> 75: public class MarryMediator : Mediator 76: { 77: public override void BlindDate(Colleague colleague, string msg) 78: { 79: colleague.Communication(msg); 80: } 81: }调用:
1: class Program 2: { 3: static void Main(string[] args) 4: { 5: Mediator mediator = new MarryMediator(); 6: 7: //红娘 8: Matchmaker matchmaker = new Matchmaker(mediator, "金牌红娘"); 9: //程序员 10: Programmer programmer = new Programmer(mediator, "光棍程序员"); 11: 12: mediator.BlindDate(matchmaker, "请问你是要相亲吗,我们这边的优质女生有很多"); 13: mediator.BlindDate(programmer, "是的,帮我介绍一个温柔贤惠的妹子吧"); 14: 15: Console.Read(); 16: } 17: }运行结果:
就这样,让人期待已久的相亲开始了,后面的事情,就交给程序员自己发挥了
优点: 中介者模式简化并理清了对象间的关系,降低了类本身的复杂度,松散了对象间的耦合 缺点: 中介者本身承担着太过沉重的职责,以至于中介者挂掉,可能系统也会挂掉
中介者模式,比较适合处理比较稳定的场景,对于一组定义比较良好的对象,预期可变性不是那么强,想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。比如在DDD领域驱动中,服务层与领域对象的交互就是一个非常稳定的场景,在这个场景里中介者模式得到了比较广泛的运用。