【转】设计模式学习笔记(17)-中介者

中介者(Mediator)模式并没有十分严格的定义,它是一种比较广泛的思想方法,”用一个中介对象来封装一系列对象的交互”。这是十分容易理解的,我们知道在网络拓扑结构中有环形、星形、总线型等多种结构,其中星形就是中介者模式。网络上的多个主机通过一台中央服务器来交流信息,各主机之间不直接通信,这样就将逻辑简化了,也保证了网络的可靠性。

其实在软件编写中有三种控制结构:集中式、分散式、委托式。集中式即所有的逻辑同通过一个类或对象来实现,分散式各自为政,委托式则是两者的折中方案。这里都是通过中介者这一对象来实现不同对象之间的交互的。

中介者模式一个十分常见的例子是GUI编程(发现很多编程模式都来自GUI啊),各个控件应该是相互独立的,都是一个个对象,但整个界面又是一个整体,如用户按下了一个按钮,某处的文本框应该清空,某处的文本标签应该变换文字等。在这种情况下,我们可以将各个控件的改变写在按钮的事件处理函数中,但这样的逻辑太复杂了,耦合度太高。如果不同时刻按下按钮想要有不同的表示呢?函数中就会充斥大量的条件判断语句(这其实可以使用后面说的状态模式来解决)。怎么办?建立一个中介对象,按钮按下后通知中介对象(可以通过观察者模式),由中介对象对其它控件的状态进行修改,各空间由彼此依赖变为依赖中介对象,降低了耦合度。

中介模式并没有十分严格的类图,但总体上来说应该是这样的:

我们这里来实现一个最简单的例子,拥有两个客户和一个中介者:

1
2
3
4
5
6
class Client
{
public:
    virtual void actionPerformed() = 0;
    virtual void dosomething() = 0;
};

定义一个通用的Client接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Mediator
{
    Client* _client1;
    Client* _client2;
public:
    void setClient1(Client* client) {
        this->_client1 = client;
    }
    void setClient2(Client* client) {
        this->_client2 = client;
    }
    void client1Call(){
        _client2->dosomething();
    }
    void client2Call(){
        _client1->dosomething();
    }
};

一个中介者,这里使用了简单粗暴的方式处理set和call方法,应用中可以使用对象注册表等方式来实现各种控件的绑定。

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
class Client1 : public Client
{
private:
    Mediator* _mediator;
 
public:
    Client1(Mediator* mediator) : _mediator(mediator) {}
    void actionPerformed(){
        _mediator->client1Call();
    }
    void dosomething(){
        cout << "client1 text set!" << endl;
    }
};
class Client2 : public Client
{
private:
    Mediator* _mediator;
public:
    Client2(Mediator* mediator) : _mediator(mediator) {}
    void actionPerformed(){
        _mediator->client2Call();
    }
    void dosomething(){
        cout << "client2 data set!" << endl;
    }
};

这是两个具体的Client对象

1
2
3
4
5
6
Mediator* mediator = new Mediator();
Client* client1 = new Client1(mediator);
Client* client2 = new Client2(mediator);
mediator->setClient1(client1);
mediator->setClient2(client2);
client1->actionPerformed();

主方法里这样调用
最终的输出结果为:

1
client2 data set!

 

从上面的代码我们可以看到,Client1中没有涉及到任何有关Client2的代码,但是Client1中的方法调用确实改变了Client2中的属性(这里表现为输出Client2中的字符串),这时中介者就起到了桥梁作用。同时我们也可以看到,随着Client的增多会倒是中介者类的膨胀,最终使得类的结构极度复杂,不易控制。

最后来看看中介者模式的适用性:

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

在实际应用中介者模式时要慎重,一旦控制不好则会增加系统的复杂度。中介者模式十分类似于Facade模式,但是Facade模式旨在分离不同系统之间的访问,而中介模式则着重于同一系统的信息交流,这是最大的不同。

 

 

转自:http://lecoding.com/articles/246.html

posted on 2013-03-05 16:25  TheKingOfKingFish  阅读(121)  评论(0)    收藏  举报

导航