设计模式(十八)—— 中介者模式
模式简介
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
通常情况下,应用程序由许多类组成,随着类数量不断增加,系统变得难以维护,主要体现在类之间的交互变得更加复杂,难以理解,修改其中一个类可能会影响到其他的类,导致整个系统崩溃。
想象机场控制塔控制飞机起飞降落的过程,飞机降落前先与机场控制塔通信,控制塔通知其它飞机暂时不要降落,跑道已经被占用了。这是一个典型的中介者模式,飞机间的通信统一通过机场控制塔,而不是各自进行通信,当某架飞机希望降落时,只需要通过控制塔,不用直接通知其它等待降落的飞机。
结构分析
UML类图
角色说明
- Mediator
抽象中介者。定义一个接口,用于同事类之间的通信。
- ConcreteMediator
具体中介者,了解并维护各个同事,协调同事对象实现协作。
- Colleague
抽象同事类
- ConcreteColleague
具体同事类,通过中介者与其它同事进行通信。
工作原理
同事向中介者对象发送和接受请求,中介者在各同事间适当地转发请求以实现协作行为。
结构代码
//抽象中介者
public interface IMediator
{
void SendMessage(string message, Colleague colleague);
}
//具体中介者
public class ConcreteMediator : IMediator
{
public ConcreteColleagueA ConcreteColleagueA { get; set; }
public ConcreteColleagueB ConcreteColleagueB { get; set; }
public void SendMessage(string message, Colleague colleague)
{
if (colleague == ConcreteColleagueA)
{
ConcreteColleagueB.Receive(message);
}
else
{
ConcreteColleagueA.Receive(message);
}
}
}
//抽象同事类
public abstract class Colleague
{
protected IMediator _mediator;
public Colleague(IMediator mediator)
{
this._mediator = mediator;
}
public abstract void Send(string message);
public abstract void Receive(string message);
}
//具体同事类A
public class ConcreteColleagueA : Colleague
{
public ConcreteColleagueA(IMediator mediator) : base(mediator)
{
}
public override void Receive(string message)
{
Console.WriteLine($"ConcreteColleagueA Receive Message:{message}");
}
public override void Send(string message)
{
Console.WriteLine($"ConcreteColleagueA Send Message:{message}");
_mediator.SendMessage(message, this);
}
}
//具体同事类B
public class ConcreteColleagueB : Colleague
{
public ConcreteColleagueB(IMediator mediator) : base(mediator)
{
}
public override void Receive(string message)
{
Console.WriteLine($"ConcreteColleagueB Receive Message:{message}");
}
public override void Send(string message)
{
Console.WriteLine($"ConcreteColleagueB Send Message:{message}");
_mediator.SendMessage(message, this);
}
}
客户端调用
static void Main(string[] args)
{
ConcreteMediator mediator = new ConcreteMediator();
ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator);
ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator);
mediator.ConcreteColleagueA = colleagueA;
mediator.ConcreteColleagueB = colleagueB;
colleagueA.Send("Hello,how are you?");
colleagueB.Send("Fine,thank you.And you?");
Console.ReadLine();
}
输出结果:
示例分析
本节讲述飞机之间通过控制塔进行通信的示例。首先创建控制塔类ControlTower,这里省略了抽象中介者。
public class ControlTower
{
private Dictionary<string, AbstractPlane> _planes = new Dictionary<string, AbstractPlane>();
public void Register(AbstractPlane plane)
{
if (!_planes.ContainsValue(plane))
{
_planes[plane.Name] = plane;
}
plane.ControlTower = this;
}
public void SendMessage(string from, string to, string message)
{
if (_planes.ContainsKey(to))
{
_planes[to].Receive(from, message);
}
}
}
声明抽象同事类AbstractPlane,并实现具体同时类AirLiner。
public abstract class AbstractPlane
{
protected string _name;
public AbstractPlane(string name)
{
_name = name;
}
public ControlTower ControlTower { get; set; }
public string Name
{
get { return _name; }
}
public abstract void Send(string to, string message);
public abstract void Receive(string from, string message);
}
public class Airliner : AbstractPlane
{
public Airliner(string name) : base(name)
{
}
public override void Receive(string from, string message)
{
Console.WriteLine($"{this.Name} Receive Message:{message} from {from}");
}
public override void Send(string to, string message)
{
ControlTower.SendMessage(this.Name, to, message);
}
}
客户端调用,向控制塔对象注册5架飞机,airLinerA通过控制塔对象与airLinerB进行通讯。
class Program
{
static void Main(string[] args)
{
ControlTower tower = new ControlTower();
Airliner airLinerA = new Airliner("A");
Airliner airLinerB = new Airliner("B");
Airliner airLinerC = new Airliner("C");
Airliner airLinerD = new Airliner("D");
Airliner airLinerE = new Airliner("E");
tower.Register(airLinerA);
tower.Register(airLinerB);
tower.Register(airLinerC);
tower.Register(airLinerD);
tower.Register(airLinerE);
airLinerA.Send("B","When will you arrive?");
airLinerB.Send("A", "Already landed.");
Console.ReadLine();
}
}
使用场景
-
一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
-
一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
-
想定制一个分布在多个类中的行为,而又不想生成太多的子类。