详解设计模式中的中介者模式在C++编程中的运用

时间:2021-10-29 12:57:37

作用:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

结构图如下:

详解设计模式中的中介者模式在C++编程中的运用

Colleage抽象同事类,而ConcreteColleage是具体同时类,每个具体同事只知道自己的行为,而不了解其他同事类的情况,但它们却都认识中介者对象,Mediator是抽象中介者,定义了同事对象到中介者对象的接口,ConcreteMediator是具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接受消息,向具体同事对象发出命令。

Colleage类,抽象同事类

Mediator,抽象中介者类

说明:

1. Mediator 模式中,每个Colleague 维护一个 Mediator,当要进行通信时,每个具体的 Colleague 直接向ConcreteMediator 发信息,至于信息发到哪里,则由 ConcreteMediator 来决定。

2. ConcreteColleagueA 和 ConcreteColleagueB 不必维护对各自的引用,甚至它们也不知道各个的存在。

3. 优点是,各个 Colleague 减少了耦合。

4. 缺点是,由于 Mediator 控制了集中化,于是就把 Colleague 之间的交互复杂性变为了中介者的复杂性,也就是中介者会变的比任何一个 Colleague 都复杂。

中介者模式很容易在系统中应用,也很容易在系统中误用。当系统中出现了“多对多”交互复杂的对象群时,不要急于使用中介者模式,而要先反思你的系统在设计上是不是合理。

Mediator的出现减少了各个Colleage的耦合,使得可以独立地改变和复用各个Colleage类和Mediator;
由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统。

由于ConcreteMediator控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这使得中介者会变得比任何一个ConcreteColleage都复杂。

中介者模式的优点来自集中控制,其缺点也是它。

中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合。

很好的例子:聊天室:

?
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Mediator pattern -- Real World example
 
 
using System;
using System.Collections;
 
namespace DoFactory.GangOfFour.Mediator.RealWorld
{
 
 // MainApp test application
 
 class MainApp
 {
  static void Main()
  {
   // Create chatroom
   Chatroom chatroom = new Chatroom();
 
   // Create participants and register them
   Participant George = new Beatle("George");
   Participant Paul = new Beatle("Paul");
   Participant Ringo = new Beatle("Ringo");
   Participant John = new Beatle("John") ;
   Participant Yoko = new NonBeatle("Yoko");
 
   chatroom.Register(George);
   chatroom.Register(Paul);
   chatroom.Register(Ringo);
   chatroom.Register(John);
   chatroom.Register(Yoko);
 
   // Chatting participants
   Yoko.Send ("John", "Hi John!");
   Paul.Send ("Ringo", "All you need is love");
   Ringo.Send("George", "My sweet Lord");
   Paul.Send ("John", "Can't buy me love");
   John.Send ("Yoko", "My sweet love") ;
 
   // Wait for user
   Console.Read();
  }
 }
 
 // "Mediator"
 
 abstract class AbstractChatroom
 {
  public abstract void Register(Participant participant);
  public abstract void Send(
   string from, string to, string message);
 }
 
 // "ConcreteMediator"
 
 class Chatroom : AbstractChatroom
 {
  private Hashtable participants = new Hashtable();
 
  public override void Register(Participant participant)
  {
   if (participants[participant.Name] == null)
   {
    participants[participant.Name] = participant;
   }
 
   participant.Chatroom = this;
  }
 
  public override void Send(
   string from, string to, string message)
  {
   Participant pto = (Participant)participants[to];
   if (pto != null)
   {
    pto.Receive(from, message);
   }
  }
 }
 
 // "AbstractColleague"
 
 class Participant
 {
  private Chatroom chatroom;
  private string name;
 
  // Constructor
  public Participant(string name)
  {
   this.name = name;
  }
 
  // Properties
  public string Name
  {
   get{ return name; }
  }
 
  public Chatroom Chatroom
  {
   set{ chatroom = value; }
   get{ return chatroom; }
  }
 
  public void Send(string to, string message)
  {
   chatroom.Send(name, to, message);
  }
 
  public virtual void Receive(
   string from, string message)
  {
   Console.WriteLine("{0} to {1}: '{2}'",
    from, Name, message);
  }
 }
 
 //" ConcreteColleague1"
 
 class Beatle : Participant
 {
  // Constructor
  public Beatle(string name) : base(name)
  {
  }
 
  public override void Receive(string from, string message)
  {
   Console.Write("To a Beatle: ");
   base.Receive(from, message);
  }
 }
 
 //" ConcreteColleague2"
 
 class NonBeatle : Participant
 {
  // Constructor
  public NonBeatle(string name) : base(name)
  {
  }
 
  public override void Receive(string from, string message)
  {
   Console.Write("To a non-Beatle: ");
   base.Receive(from, message);
  }
 }
}

适用场景:

  • 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
  • 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
  • 想定制一个分布在多个类中的行为,而又不想生成太多的子类。