动机

在面向对象的设计中,鼓励将行为封装到各自的对象中,这就会导致如果一个动作涉及多个类对象之间的互动时,往往导致类与类之间的关系错综复杂。显然,这不利于后续的维护和扩展。
中介者类似于“加一层”的思想,将涉及多个类对象之间的动作封装到中介者类中,由中介者进行协调控制,而其他的类对象只需要知道中介者这个类就可以了,执行动作时,不需要再去和其他类交互。
中介者形象上类似于一个货物中转中心,负责调配所有的中转方案。

示例

还是用货物中转举例,现在我们有以下的几种货物到达了中转站,但入口只有一个,需要决定谁先进去,如果让这几种货物协商,那么每个货物对象都需要知道对象的存在,这无疑增大了对象间的耦合性。

1
2
3
4
5
class FruitGoods;

class ClothesGoods;

class SeafoodGoods;

于是我们选择让中介者来决定,所有货物到达后通知中介者,中介者再通知该货物等待多久后进入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
std::random_device seed;
std::default_random_engine eng(seed());
std::uniform_int_distribution<int> generator(1, 5);

class Goods;

class GoodsMediator {
public:
void registerGoods(Goods& goods) {
m_goodslist.push_back(goods);
}

int notify() {
return generator(eng);
}

private:
std::vector<Goods> m_goodslist{};
};

class Goods {
public:
Goods(GoodsMediator& mediator) : m_mediator(mediator) {
mediator.registerGoods(*this);
}

virtual void waitEnter() {
std::cout << "wait for " << m_mediator.notify() << " s\n";;
}

protected:
GoodsMediator& m_mediator;
};

class FruitGoods : public Goods {
public:
FruitGoods(GoodsMediator& mediator) : Goods(mediator) { }

void waitEnter() {
cout << "fruit: ";
Goods::waitEnter();

}
};

class ClothesGoods : public Goods {
public:
ClothesGoods(GoodsMediator& mediator) : Goods(mediator) { }

void waitEnter() {
cout << "clothes: ";
Goods::waitEnter();
}
};

class SeafoodGoods : public Goods {
public:
SeafoodGoods(GoodsMediator& mediator) : Goods(mediator) { }

void waitEnter() {
cout << "seafood: ";
Goods::waitEnter();
}
};

int main() {
GoodsMediator mediator;
FruitGoods fruit(mediator);
ClothesGoods clothes(mediator);
SeafoodGoods seafood(mediator);

fruit.waitEnter();
clothes.waitEnter();
seafood.waitEnter();

return 0;
}

结果可能如下:

1
2
3
fruit: wait for 3 s
clothes: wait for 2 s
seafood: wait for 4 s

通过加入了中介者这一层,货物之间的耦合性降低了,货物只需要知道中介者,并且将自己注册给中介者即可。

适用性

  • 一组对象通过一些定义良好但复杂的方式进行通讯,产生的依赖关系过于混乱而难以理解。
  • 一个对象需要和多个对象直接通信,导致这个对象难以复用。
  • 希望定制一些涉及多个类的行为,但是又不想生成太多的子类。