设计模式学习总结-中介者模式(Mediator Method)
问题:
在面向对象系统的设计和开发过程中,对象之间的交互和通信是最为常见的情况。在系统比较小的时候,可能对象间的通信不是很多、对象也比较少,我
们可以直接硬编码到各个对象的方法中。但是当系统规模很大,需要通讯的对象很多,这种硬编码的形式,就会造成系统对象相互交错依赖(如当我们完
成某种操作时,同时要改变对象B的结果,又要将结果传给C对象,C有可能接收改变后影响D对象...),每个对象与相互通信的对象之间都要维护一个引
用,对象间的通信也变得越来越复杂,有没有一种办法可以使各个对象间的通信不必显势去声明和引用,来降低了系统的复杂性能并降低各个对象之间的
紧耦合?
定义:
中介者模式(Mediator Pattern)是一种行为模式,定义一个中介对象来封装系列对象之间的交互。中介者使各个对象不需要显示地相互引用,从而使其
耦合性松散,而且可以独立地改变他们之间的交互。
意图:
Mediator模式中,每个Colleague维护一个Mediator的引用,当同事类需要交互时,可以通过Concrete Mediator提供的交互方法来处理,Concrete
Mediator接收发送消息类传递的消息,并调用接收类的方法接收消息,交互的同事类不必维护对各自的引用,甚至它们也不知道各个的存在。Mediator模
式通过这种方式将多对多的通信简化为了一(Mediator)对多(Colleague)的通信。
参与者:
•抽象中介者(Mediator)角色:
定义了同事对象交互的接口。
•具体中介者对象(ConcreteMediator)角色:
实现抽象类中的方法,此具体中介者对象需要知道所有具体同事类,并从具体同事接受消息,向具体同事对象发送命令。
•抽象同事(Colleague)角色:
定义了具体同事角色的公用接口。 每个同事类的行为分为两种:第一种是同事角色本身的行为,不与其他同事角色或中介者交互的方法,这种方法叫做
自发行为(Self-Method);第二种是必须依赖中介者才能完成的行为,叫做依赖方法(Dep-Method)。
具体同事类(ConcreteColleague)角色:具体同事角色,实现抽象同事类中的方法。每一个同时类需要知道中介者对象;每个具体同事类只需要了解自
己的行为,而不需要了解其他同事类的情况。
UML:
代码说明:
/// The 'Mediator' abstract class
/// </summary>
abstract class MediatorClass
{
public abstract void Send(string message, Colleague colleague);
}
/// <summary>
/// The 'ConcreteMediator' class
/// </summary>
class ConcreteMediator : MediatorClass
{
//维护了相互通信对象的引用
private ConcreteColleagueB _colleague1;
private ConcreteColleagueA _colleague2;
public ConcreteColleagueB Colleague1
{
set { _colleague1 = value; }
}
public ConcreteColleagueA Colleague2
{
set { _colleague2 = value; }
}
/// <summary>
/// 对象间通讯方法
/// </summary>
/// <param name="message"></param>
/// <param name="colleague"></param>
public override void Send(string message, Colleague colleague)
{
if (colleague == _colleague1)
{
_colleague2.Notify(message);
}
else
{
_colleague1.Notify(message);
}
}
}
/// <summary>
/// The 'Colleague' abstract class
/// </summary>
abstract class Colleague
{
protected MediatorClass mediator;
// Constructor
public Colleague(MediatorClass mediator)
{
this.mediator = mediator;
}
}
/// <summary>
/// A 'ConcreteColleague' class
/// </summary>
class ConcreteColleagueB : Colleague
{
// Constructor
public ConcreteColleagueB(MediatorClass mediator)
: base(mediator)
{
}
public void Send(string message)
{
mediator.Send(message, this);
}
public void Notify(string message)
{
Console.WriteLine("ColleagueA gets message: " + message);
}
}
/// <summary>
/// A 'ConcreteColleague' class
/// </summary>
class ConcreteColleagueA : Colleague
{
// Constructor
public ConcreteColleagueA(MediatorClass mediator)
: base(mediator)
{
}
public void Send(string message)
{
mediator.Send(message, this);
}
public void Notify(string message)
{
Console.WriteLine("ColleagueB gets message: " + message);
}
}
void Mediator1Test(string[] args)
{
ConcreteMediator m = new ConcreteMediator();
ConcreteColleagueB c1 = new ConcreteColleagueB(m);
ConcreteColleagueA c2 = new ConcreteColleagueA(m);
m.Colleague1 = c1;
m.Colleague2 = c2;
c1.Send("How are you? JamesHao");
c2.Send("Fine, thanks");
// Wait for user
Console.ReadKey();
}
实例说明:
诺基亚手机工厂
聊天室多人(多个对象)聊天通讯代码
uml图如下:
代码:
/// The 'Mediator' abstract class
/// </summary>
abstract class AbstractChatroom
{
public abstract void Register(Participant participant);
public abstract void Send(string from, string to, string message);
}
/// <summary>
/// The 'ConcreteMediator' class
/// </summary>
class Chatroom : AbstractChatroom
{
private Dictionary<string, Participant> _participants = new Dictionary<string, Participant>();
public override void Register(Participant participant)
{
if (!_participants.ContainsValue(participant))
{
_participants[participant.Name] = participant;
}
participant.Chatroom = this;
}
public override void Send(string from, string to, string message)
{
Participant participant = _participants[to];
if (participant != null)
{
participant.Receive(from, message);
}
}
}
/// <summary>
/// 参与者Participant类
/// </summary>
class Participant
{
private Chatroom _chatroom;
private string _name;
// Constructor
public Participant(string name)
{
this._name = name;
}
// Gets participant name
public string Name
{
get { return _name; }
}
// Gets chatroom
public Chatroom Chatroom
{
set { _chatroom = value; }
get { return _chatroom; }
}
// Sends message to given participant
public void Send(string to, string message)
{
_chatroom.Send(_name, to, message);
}
// Receives message from given participant
public virtual void Receive(string from, string message)
{
Console.WriteLine("{0} to {1}: '{2}'", from, Name, message);
}
}
void Mediator2Test()
{
// Create chatroom
Chatroom chatroom = new Chatroom();
// Create participants and register them
Participant George = new Participant("George");
Participant Paul = new Participant("Paul");
Participant Ringo = new Participant("Ringo");
Participant John = new Participant("John");
Participant Yoko = new Participant("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.ReadKey();
}
优点:
•中介者模式的优点是减少了类之间的依赖,使原有一对多的依赖变成了一对一的依赖,同事类只依赖中介者,降低了类之间的耦合。
缺点:
•中介者模式的缺点是中介者会膨胀的很大,而且逻辑复杂,同事类越多,中介者逻辑越复杂。
应用场景:
•一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
•一个对象引用很多其他对象并直接与这些对象通信,导致难以复用该对象。
•想定制一个分部在多个类中的行为,而又不想生成太多的子类。