中介者模式简介
提供一个中介对象出来,用于封装一系列对象的交互,从而使各对象不需要直接交互,进一步降低了对象间的耦合度。这是一种行为型设计模式。
由此可见,中介者模式主要解决的是对象间所存在的大量关系,我们都知道,对象间一旦关联紧密,必然会导致系统的复杂性增加,一旦某个对象有所修改,其关联对象也有可能会有跟着更改,这自然不是我们所希望的。有些朋友可能会说,如果交互很多,是不是可以将对象合并,从某种角度上来说,我们可以考虑对象合并。但是,我们并不能这样去做,因为对象存在的层级可能是不同的,有些是处理数据交互的,有些是处理业务级的,合并起来会导致系统层次不明,引入更大的风险。
在现实生活中,中介者更多的体现为调度平台或者房产中介,再或者就是红娘了。我们以红娘为例,
程序员找个女朋友实在是太难,而且时间也不多,圈子也不大,一个一个去认识,鬼知道哪一个要找对象的,耗费精力不说,尼玛,还少敲了好几段代码。所以,一般通过红娘会更方便一点,会使得我们的目的更加明确,就是找对象,筛选、信息收集、匹配的事情交给红娘做就好了。毕竟红娘可是掌握着很多女孩子的信息及其择偶要求的,程序员过去把信息或者要求填写一下即可,红娘帮你匹配合适的女孩子,一旦有较高的匹配度,就可以约会见见了,说不准很快就成了,这样代码没少敲,对象也不耽误找,是不是很爽……
以上,我们可以发现,在中介者模式里面,中介者承担的职能主要包括:
- 业务通道的聚合,把之前繁琐的对象交互抽象出来,所有的交互通过中介者通道进行。
- 信息的中转,在中介者模式里,对象间的信息通过中介者转发到对应的对象处。
中介者UML类图
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领域驱动中,服务层与领域对象的交互就是一个非常稳定的场景,在这个场景里中介者模式得到了比较广泛的运用。