设计模式(十八)—— 中介者模式

模式简介


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

通常情况下,应用程序由许多类组成,随着类数量不断增加,系统变得难以维护,主要体现在类之间的交互变得更加复杂,难以理解,修改其中一个类可能会影响到其他的类,导致整个系统崩溃。

想象机场控制塔控制飞机起飞降落的过程,飞机降落前先与机场控制塔通信,控制塔通知其它飞机暂时不要降落,跑道已经被占用了。这是一个典型的中介者模式,飞机间的通信统一通过机场控制塔,而不是各自进行通信,当某架飞机希望降落时,只需要通过控制塔,不用直接通知其它等待降落的飞机。

结构分析


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();
    }
}

使用场景


  • 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。

  • 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
  • 想定制一个分布在多个类中的行为,而又不想生成太多的子类。

posted @ 2018-07-10 19:38 Answer.Geng 阅读(...) 评论(...) 编辑 收藏