您的位置:首页 > 其它

设计模式之Mediator(中介者)模式(应用篇)

2012-04-11 22:22 831 查看
本文编辑整理自:
http://blog.csdn.net/haiyan0106/article/details/1651719
一、什么是中介者模式

    Mediator模式也叫中介者模式,是由GoF提出的23种软件设计模式的一种。Mediator模式是行为模式之一,在Mediator模式中,类之间的交互行为被统一放在Mediator的对象中,对象通过Mediator对象同其他对象交互,Mediator对象起着控制器的作用。

关于Mediator模式的更多理论知识请参考《设计模式之Mediator(中介者)模式(理论篇)
二、何时使用中介者模式

   各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉及到修改很多其他对象的行为,如果使用Mediator模式,可以使各个对象间的耦合松散,只需关心和 Mediator的关系,使多对多的关系变成了一对多的关系,可以降低系统的复杂性,提高可修改扩展性。

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

   Mediator模式是GoF的23种设计模式中较为容易理解的一个,我们在平时的应用中也会经常用到,但可能不会有意去抽象出一个完整的Mediator类,因为要设计一个可复用又可扩展的Mediator是很不容易的。

  Mediator模式的主要作用在于为多个对象之间的交互提供一种媒介,以简化对象之间的耦合关系。下面用两个实例来说明Mediator模式的应用。
3.1、ChatRoom(聊天室)示例

  聊天室大家想必都知道,在下面的示例中,我们尝试实现一个布告栏式的ChatRoom,任何人想要发送消息给其他人,只需将消息发送给ChatRoom对象,由ChatRoom负责数据的转发,而不是直接与消息的接收者交互。后面的笔记中将从Observer模式的角度来解决ChatRoom问题。
#include <iostream>

#include <string>

#include <map>
using namespace std;

class Participant;

// "AbstractMediator"
struct IChatroom

{

  // Methods
  virtual void Register( Participant* participant ) = 0;

  virtual void Send( string& from, string& to, string& message ) = 0;

};

// "AbstractColleague"
class Participant

{

    friend class Chatroom;

    // Fields
private:

    IChatroom* pChatroom;

    string name;

    // Constructors
public:

    /*Participant()

    {

    }*/

    Participant( const char* name )

    {

        this->name = name;

    }

    virtual ~Participant()

    {

    }

    // Methods
    virtual void Send( string& to, string& message )

    {

        pChatroom->Send( name, to, message );

    }

    virtual void Receive( string& from, string& message )

    {

        cout << from.c_str() << " to " << name.c_str() << " : [" << message.c_str() << "]" << endl;

    }

};

// More ConcreteColleague, omitted...

// "ConcreteMediator"
class Chatroom : public IChatroom

{

    // Fields
private:

    map<string, Participant*> mapParticipants;    // nickname to Participant map

    // Methods
public:

    void Register( Participant* pParticipant )

    {

        mapParticipants[ pParticipant->name ] = pParticipant;

        pParticipant->pChatroom = this;

    }

    void Send( string& from, string& to, string& message )

    {

        map<string, Participant*>::iterator ptr;

        ptr = mapParticipants.find(to);

        if ( ptr != mapParticipants.end() )

        {

            Participant* pto = (*ptr).second;

            pto->Receive( from, message );

        }

    }

};

int main()

{

    // Create chatroom
    Chatroom c;

    // Create 'chatters' and register them
    Participant George("George");

    Participant Paul("Paul");

    Participant Ringo("Ringo");

    c.Register( &George );

    c.Register( &Paul );

    c.Register( &Ringo );

    // Chatting participants
    George.Send( string("Paul"), string("Hi Paul!") );

    Paul.Send( string("Ringo"), string("Good Morning!") );

    Ringo.Send( string("George"), string("Hi Friend!") );

    return 0;

}

3.2、多线程Producer-Consumer(生产者和消费者示例)

  以下是一个多线程Producer-Comsumer的例子,在该示例中,由于无法在多个Producer、Cosumer之间建立直接的联系,因此,通过Mediator类来完成这种信息交互,当Producer要Produce时,只需与Mediator进行交互,以查询是否有空的Slot可供存放Product,而Comsumer要Comsume时,也只需与Mediator进行交互,以查询是否有Product可供Comsume。

以下是该示例的Java实现:

import java.util.*;

class Product {

    int id;

    Product(int id) {

        this.id = id;

    }

}

class Mediator {

    private boolean stopFlag = false;

    private Stack slot = new Stack();

    private int slotCount;

    public Mediator(int slotCount) {

        this.slotCount = slotCount;

    }

    public boolean stop() {

        return stopFlag;

    }

    public void stop(boolean flag) {

        stopFlag = true;

    }

    public boolean put(Product product) {

        synchronized( slot ) {    // or synchronized on Mediator.class, but on slot is better and reasonable
            if ( slot.size() >= slotCount ) {

                return false;

            }

            slot.push( product );

        }

        return true;

    }

    public Product get() {

        synchronized( slot ) {

            if ( slot.empty() )

                return null;

            Product product = (Product)slot.pop();

            return product;

        }

    }

}

class Producer extends Thread {

    private Mediator med;

    private int id;

    private static int num = 1;

    public Producer(Mediator m) {

        med = m;

        id = num++;

    }

    public void run() {

        Product product;

        while ( !med.stop() ) {

            product = new Product((int) (Math.random() * 100));

            synchronized (System.out) {

                System.out.println("Producer[" + id + "] produces Product["

                    + product.id + "]");

            }

            while ( !med.stop() && !med.put(product) ) { // if put failed, try to put again and again.
                try {

                    sleep( 100 );

                } catch (InterruptedException ie) {

                }

            }

            try {

                sleep( 100 );

            } catch (InterruptedException ie) {

            }

        }

    }

}

class Consumer extends Thread {

    private Mediator med;

    private int id;

    private static int num = 1;

    public Consumer(Mediator m) {

        med = m;

        id = num++;

    }

    public void run() {

        Product product;

        while ( !med.stop() ) {

            product = med.get();

            if ( product != null ) {

                synchronized (System.out) {

                    System.out.println("Consumer[" + id + "] is consuming Product["

                        + product.id + "]");

                }

            }

            try {

                sleep( 100 );

            } catch (InterruptedException ie) {

            }

        }

    }

}

class MediatorDemo {

    public static void main(String[] args) {

        Mediator med = new Mediator(2);

        Thread thread[] = { new Producer(med), new Producer(med),

                new Consumer(med), new Consumer(med), new Consumer(med) };

        for (int i = 0; i < thread.length; i++)

            thread[i].start();

        // before stop all threads, sleep 1 second
        try {

            Thread.sleep(1000);

        } catch (InterruptedException ie) {

        }

        med.stop(true);

        // Wait for all threads to return
        try {

            for (int i = 0; i < thread.length; i++) {

                thread[i].join();

            }

        } catch (InterruptedException ie) {

        }

    }

}

结束!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息