25. 中介者模式
约 1503 字大约 5 分钟
2026-03-27
定义
中介者模式(Mediator),用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
人话:中介者模式就像 联合国 和 各个国家之间的关系。世界上有很多国家,如果每个国家之间都直接沟通、谈判、协商,那么关系会变得非常复杂,比如 A 国要和 B、C、D……分别沟通,B 国也要和其他国家逐个联系,很容易出现信息混乱、沟通成本极高的问题。
如果不用中介者模式来设计,就相当于每个国家之间都要两两直接通信,一旦国家数量变多,通信关系就会呈指数级增长。这在软件中就属于对象之间耦合过高、关系网复杂、难以维护。
而使用中介者模式之后,就相当于引入了“联合国”这个中间机构。各个国家不再彼此直接沟通,而是把自己的诉求、消息都提交给联合国,由联合国来进行转发、协调和处理。
这样一来:
- 各个国家只需要和“联合国”打交道(Colleague)
- 联合国负责协调各方关系(Mediator)
- 国家之间的通信全部通过联合国转发
比如:
- A 国提出请求 → 交给联合国
- 联合国判断 → 转发给相关国家
- 其他国家再通过联合国进行回应
在软件中也是一样:中介者模式通过引入一个中介对象,把多个对象之间复杂的交互关系集中管理起来。各个对象不再直接引用彼此,而是通过中介者通信,从而降低耦合、简化关系结构,让系统更加清晰、易于维护和扩展。
中介者模式(Mediator)结构图
Mediator类——抽象中介者:
// Mediator(抽象中介者)
abstract class Mediator
{
// 定义发送消息的方法
public abstract void Send(string message, Colleague colleague);
}Colleague类——抽象同事类:
// Colleague(抽象同事类)
abstract class Colleague
{
protected Mediator mediator;
// 构造方法,得到中介者对象
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
}ConcreteMediator类——具体中介者:
// ConcreteMediator(具体中介者)
class ConcreteMediator : Mediator
{
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
// 设置同事对象
public ConcreteColleague1 Colleague1
{
set { colleague1 = value; }
}
public ConcreteColleague2 Colleague2
{
set { colleague2 = value; }
}
// 重写发送方法
public override void Send(string message, Colleague colleague)
{
if (colleague == colleague1)
{
colleague2.Notify(message);
}
else
{
colleague1.Notify(message);
}
}
}ConcreteColleague1类——具体同事类1:
// ConcreteColleague1
class ConcreteColleague1 : Colleague
{
public ConcreteColleague1(Mediator mediator)
: base(mediator)
{
}
// 发送消息
public void Send(string message)
{
mediator.Send(message, this);
}
// 接收消息
public void Notify(string message)
{
Console.WriteLine("同事1得到信息:" + message);
}
}ConcreteColleague2类——具体同事类2:
// ConcreteColleague2
class ConcreteColleague2 : Colleague
{
public ConcreteColleague2(Mediator mediator)
: base(mediator)
{
}
// 发送消息
public void Send(string message)
{
mediator.Send(message, this);
}
// 接收消息
public void Notify(string message)
{
Console.WriteLine("同事2得到信息:" + message);
}
}客户端代码:
static void Main(string[] args)
{
ConcreteMediator m = new ConcreteMediator();
ConcreteColleague1 c1 = new ConcreteColleague1(m);
ConcreteColleague2 c2 = new ConcreteColleague2(m);
// 让中介者认识各个同事
m.Colleague1 = c1;
m.Colleague2 = c2;
// 同事之间通过中介者通信
c1.Send("吃过饭了吗?");
c2.Send("没有呢,你打算请客?");
Console.Read();
}运行结果:
同事2得到信息:吃过饭了吗?
同事1得到信息:没有呢,你打算请客?中介者模式很容易在系统中应用,也很容易在系统中误用。当系统出现了‘多对多’交互复杂的对象群时,不要急于使用中介者模式,而要先反思你的系统在设计上是不是合理。
中介者模式的优点首先是 Mediator 的出现减少了各个 Colleague 的耦合,使得可以独立地改 变和复用各个 Colleague 类和 Mediator ,比如任何国家的改变不会影响到其他国家,而只是与安理会发 生变化。其次,由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中, 这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去 看待系统。比如巴以冲突,本来只能算是国与国之间的矛盾,因此各自的看法可能都比较狭隘,但站在 联合国安理会的角度,就可以从全球化、也更客观角度来看待这个问题,在调停和维和上做出贡献。
那中介者模式的缺点呢?具体中介者类 ConcreteMediator 可能会因为 ConcreteColleague 的越来越多, 而变得非常复杂,反而不容易维护了。由于 ConcreteMediator 控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这就使得中介者会变得比任何一个 ConcreteColleague 都复杂。事实上,联合国安理会秘书长的工作应该是非常繁忙的,谁叫他就是‘全球最大的官’呢。也正因为此,中介者模式的优点来自集中控制,其缺点也是它,使用时是要考虑清楚哦。
