中介者模式

在软件工程领域，中介者模式定义了一个中介者对象，该对象封装了系统中对象间的交互方式。 由于它可以在运行时改变程序的行为，这种模式是一种行为型模式 。
通常程序由大量的类组成，这些类中包含程序的逻辑和运算。 然而，当开发者将更多的类加入到程序中之后，类间交互关系可能变得更为复杂，这会使得代码变得更加难以阅读和维护，尤其是在重构的时候。 此外，程序将会变得难以修改，因为对其所做的任何修改都有可能影响到其它几个类中的代码。
在中介者模式中，“同事”对象间的通信过程被封装在一个“中介者”（调解人）对象之中。 对象之间不再直接交互，而是通过调解人进行交互。 这么做可以减少可交互对象间的依赖，从而降低耦合。
概述.
中介者模式是23个周知模式（ 即GoF《设计模式》）中的一个，GoF设计模式旨在提供重复出现的设计问题的解决方案，以编写灵活和可复用的面向对象软件。也就是说，使对象更加易于实现、修改、测试和复用。
中介者设计模式可以解决什么问题？
使用直接逐个访问并更新彼此的方式进行对象间的交互灵活性低，因为这种方式使对象彼此间紧密耦合，导致不可能单独修改类间交互关系本身，而不影响关系中进行交互的类。并且这种方式会令对象变得无法复用，并且难以测试。
由于“紧耦合”的对象过多了解其他对象的内部细节，这种对象难以实现、修改、测试以及复用。
中介者模式如何解决上述问题？
对象利用中介者对象与其他对象进行间接交互，中介者对象负责控制和协调交互关系，这么做可使得对象间“松耦合”。这些对象只访问中介者，不了解其他对象的细节。另见UML类图和时序图如下。
定义.
中介者模式是为了“定义一个封装了对象间交互关系的对象”。这种方式避免了显式调用其他类，促进了类间的松耦合，并且使得类间交互关系本身可以单独修改。客户类可以使用中介者向其他客户类发送信息，并且通过中介者引发的事件收到信息。
结构.
在以上UML类图中，类codice_1和codice_2不引用和更新彼此。相反，它们引用一个通用的codice_3接口以实现类间交互的控制和协调(通过codice_4)，这使得它们独立于类间交互的具体细节。类codice_5实现了类codice_1和codice_2之间的交互细节。
上述UML时序图显示了这些类之间在运行时的交互过程：在这个例子中，一个codice_5对象中介，即控制和协调了codice_1和codice_2的对象之间的交互。
如果codice_1的对象需要与codice_2的对象进行交互，例如更新或者同步状态，codice_1调用codice_5对象的codice_15方法，以此得到对codice_1对象（自己）的改动信息，并且在codice_2的对象上执行codice_18方法。
此后，codice_2对象调用codice_5对象的codice_15方法，得到对codice_2（自己）的修改的数据，并且对codice_1对象调用codice_24 方法。
范例.
Java.
在以下示例中，一个中介者对象控制了三个互相交互的按钮的状态，为此它有设置状态的三个方法：codice_28, codice_29 和 codice_30。 当相应的按钮被激活时，对应的方法通过codice_31方法被调用。
于是这里在交互中每个交互的参与者（本例中即按钮）将自己的行为提交给中介者并且由中介者将这些行为转给对应的参与者。
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
//Colleague interface
interface Command {
 void execute();
//Abstract Mediator
interface Mediator {
 void book();
 void view();
 void search();
 void registerView(BtnView v);
 void registerSearch(BtnSearch s);
 void registerBook(BtnBook b);
 void registerDisplay(LblDisplay d);
//Concrete mediator
class ParticipantMediator implements Mediator {
 BtnView btnView;
 BtnSearch btnSearch;
 BtnBook btnBook;
 LblDisplay show;
 public void registerView(BtnView v) {
 btnView = v;
 public void registerSearch(BtnSearch s) {
 btnSearch = s;
 public void registerBook(BtnBook b) {
 btnBook = b;
 public void registerDisplay(LblDisplay d) {
 show = d;
 public void book() {
 btnBook.setEnabled(false);
 btnView.setEnabled(true);
 btnSearch.setEnabled(true);
 show.setText("booking...");
 public void view() {
 btnView.setEnabled(false);
 btnSearch.setEnabled(true);
 btnBook.setEnabled(true);
 show.setText("viewing...");
 public void search() {
 btnSearch.setEnabled(false);
 btnView.setEnabled(true);
 btnBook.setEnabled(true);
 show.setText("searching...");
//A concrete colleague
class BtnView extends JButton implements Command {
 Mediator med;
 BtnView(ActionListener al, Mediator m) {
 super("View");
 addActionListener(al);
 med = m;
 med.registerView(this);
 public void execute() {
 med.view();
//A concrete colleague
class BtnSearch extends JButton implements Command {
 Mediator med;
 BtnSearch(ActionListener al, Mediator m) {
 super("Search");
 addActionListener(al);
 med = m;
 med.registerSearch(this);
 public void execute() {
 med.search();
//A concrete colleague
class BtnBook extends JButton implements Command {
 Mediator med;
 BtnBook(ActionListener al, Mediator m) {
 super("Book");
 addActionListener(al);
 med = m;
 med.registerBook(this);
 public void execute() {
 med.book();
class LblDisplay extends JLabel {
 Mediator med;
 LblDisplay(Mediator m) {
 super("Just start...");
 med = m;
 med.registerDisplay(this);
 setFont(new Font("Arial", Font.BOLD, 24));
class MediatorDemo extends JFrame implements ActionListener {
 Mediator med = new ParticipantMediator();
 MediatorDemo() {
 JPanel p = new JPanel();
 p.add(new BtnView(this, med));
 p.add(new BtnBook(this, med));
 p.add(new BtnSearch(this, med));
 getContentPane().add(new LblDisplay(med), "North");
 getContentPane().add(p, "South");
 setSize(400, 200);
 setVisible(true);
 public void actionPerformed(ActionEvent ae) {
 Command comd = (Command) ae.getSource();
 comd.execute();
 public static void main(String[] args) {
 new MediatorDemo();
C#.
中介者模式确保了构件之间的松耦合，使得它们不直接调用彼此，而是通过中介者调用彼此。 在下面的例子中，调解人注册了所有的构件，然后调用了它们的SetState方法。
public interface IComponent {
 void SetState(object state);
public class Component1 : IComponent {
 public void SetState(object state) {
 throw new NotImplementedException();
public class Component2 : IComponent {
 public void SetState(object state) {
 throw new NotImplementedException();
// Mediates the common tasks
public class Mediator {
 public void ChangeState(object state) {
 this.Component1.SetState(state);
 this.Component2.SetState(state);
一个聊天室，或者一个需要客户彼此间每次发送消息之后执行动作的系统（对聊天室来说就是每个人之间发送消息）可以使用中介者模式。但实际上对聊天室使用中介者模式只在包含远程功能时有用。 原生的套接字不允许委托回呼函式（即通过中介者类订阅的 MessageReceived 事件）。
public delegate void MessageReceivedEventHandler(string message, string from);
public class Mediator {
 public event MessageReceivedEventHandler MessageReceived;
 public void Send(string message, string from) {
 if (MessageReceived != null) {
 Console.WriteLine("Sending '{0}' from {1}", message, from);
 MessageReceived(message, from);
public class Person {
 private Mediator _mediator;
 public Person(Mediator mediator, string name) {
 Name = name;
 _mediator = mediator;
 _mediator.MessageReceived += new MessageReceivedEventHandler(Receive);
 private void Receive(string message, string from) {
 if (from != Name)
 Console.WriteLine("{0} received '{1}' from {2}", Name, message, from);
 public void Send(string message) {
 _mediator.Send(message, Name);
Python.
下面是Python的例子：
from abc import ABC, abstractmethod
class Colleague(ABC):
 @abstractmethod
 def get_state(self): pass
 @abstractmethod
 def set_state(self): pass
 @abstractmethod
 def action(self): pass
 @abstractmethod
 def mediate_with(self, other): pass
class ColleagueA(Colleague):
 def __init__(self, mediator):
 self.state = []
 self.mediator = mediator
 mediator.register_colleague(self)
 def get_state(self):
 return self.state, self.kwstate
 def set_state(self, *args, **kwargs):
 self.state = args
 self.kwstate = kwargs
 def action(self, other, *args, **kwargs):
 print(self, "Got", args, kwargs, "From", other)
 def mediate_with(self, other):
 self.mediator.mediate(self, other)
class Mediator():
 def __init__(self):
 self.__colleagues = []
 def register_colleague(self, coll):
 self.__colleagues.append(coll)
 def unregister_colleague(self, coll):
 self.__colleagues.remove(coll)
 def mediate(self, src, dest):
 assert src in self.__colleagues
 assert dest in self.__colleagues
 temp0, temp1 = src.get_state()
 dest.action(src, *temp0, **temp1)
其执行：
»&gt; mediator = Mediator()
»&gt; colleague1 = ColleagueA(mediator)
»&gt; colleague2 = ColleagueA(mediator)
»&gt; colleague1.set_state("test", kw="python")
»&gt; colleague1.mediate_with(colleague2)
&lt;__main__.ColleagueA object at 0x7d60b1bb7ed0&gt; Got ('test',) {'kw': 'python'} From &lt;__main__.ColleagueA object at 0x7d60b1a54980&gt;