中介者模式(Mediator)

参考:

中介者设计模式 (refactoringguru.cn)

design-patterns-cpp/Mediator.cpp at master · JakubVojvoda/design-patterns-cpp · GitHubhttps://github.com/JakubVojvoda/design-patterns-cpp/blob/master/command/Command.cpp)

2. 中介者模式 — Graphic Design Patterns (design-patterns.readthedocs.io)

一、什么是中介者模式?

中介者模式定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。

对于一个模块,可能由很多对象构成,而且这些对象之间可能存在相互的引用,为了减少对象两两之间复杂的引用关系,使之成为一个松耦合的系统,我们需要使用中介者模式,这就是中介者模式的模式动机。

如房屋买卖,有了中介的出现,不需要买家与卖家之间有任何联系也能实现交易。

在这里插入图片描述

二、实现

中介者(Mediator)模式包含以下主要角色:

1、抽象中介者(Mediator):接口声明了与组件交流的方法,但通常仅包括一个通知方法。组件可将任意上下文(包括自己的对象)作为该方法的参数,只有这样接收组件和发送者类之间才不会耦合。
2、具体中介者(Concrete Mediator):封装了多种组件间的关系。具体中介者通常会保存所有组件的引用并对其进行管理,甚至有时会对其生命周期进行管理。
3、抽象同事类(Colleague):是各种包含业务逻辑的类。每个同事都有一个指向中介者的引用,该引用被声明为中介者接口类型。同事不知道中介者实际所属的类,因此你可通过将其连接到不同的中介者以使其能在其他程序中复用。
4、具体同事类(Concrete Colleague):同事并不知道其他同事的情况。如果同事有重要事件通知,他只能通知中介者。中介者收到通知后能轻易地确定发送者,这或许已足以判断接下来需要接收的同事了。


在这里插入图片描述

/*
 * C++ Design Patterns: Mediator
 * Author: Jakub Vojvoda [github.com/JakubVojvoda]
 * 2016
 *
 * Source code is licensed under MIT License
 * (for more details see LICENSE)
 *
 */

#include <iostream>
#include <vector>
#include <string>

class Mediator;

/*
 * 同事类
 * 当他需要与其它同事交流时,需要通过中介者才能发送消息
 */
class Colleague
{
public:
  Colleague( Mediator* const m, const unsigned int i ) : 
    mediator( m ), id( i ) {}
  
  virtual ~Colleague() {}
  
  unsigned int getID()
  {
    return id;
  }
  
  virtual void send( std::string ) = 0;
  virtual void receive( std::string ) = 0;

protected:
  Mediator *mediator;
  unsigned int id;
};

class ConcreteColleague : public Colleague
{
public:
  ConcreteColleague( Mediator* const m, const unsigned int i ) : 
    Colleague( m, i ) {}
  
  ~ConcreteColleague() {}
  
  void send( std::string msg );
  
  void receive( std::string msg )
  {
    std::cout << "Message '" << msg << "' received by Colleague " << id << std::endl;
  }
};

/*
 * 中介者接口类
 * 定义所有同事类通信的接口。
 */
class Mediator
{
public:
  virtual ~Mediator() {}
  
  virtual void add( Colleague* const c ) = 0;
  virtual void distribute( Colleague* const sender, std::string msg ) = 0;

protected:
  Mediator() {}
};

/*
 * 具体中介者
 * 实现某已知同事之间的沟通方式
 */
class ConcreteMediator : public Mediator
{
public:
  ~ConcreteMediator()
  {
    for ( unsigned int i = 0; i < colleagues.size(); i++ )
    {
      delete colleagues[ i ];
    }
    colleagues.clear();
  }
  
  void add( Colleague* const c )
  {
    colleagues.push_back( c );
  }
  
  void distribute( Colleague* const sender, std::string msg )
  {
    for ( unsigned int i = 0; i < colleagues.size(); i++ )
    {
      if ( colleagues.at( i )->getID() != sender->getID() )
      {
        colleagues.at( i )->receive( msg );
      }
    }
  }

private:
  std::vector<Colleague*> colleagues;
};

void ConcreteColleague::send( std::string msg )
{
  std::cout << "Message '"<< msg << "' sent by Colleague " << id << std::endl;
  mediator->distribute( this, msg );
}


int main()
{
  Mediator *mediator = new ConcreteMediator();
  
  Colleague *c1 = new ConcreteColleague( mediator, 1 );
  Colleague *c2 = new ConcreteColleague( mediator, 2 );
  Colleague *c3 = new ConcreteColleague( mediator, 3 );
  
  mediator->add( c1 );
  mediator->add( c2 );
  mediator->add( c3 );
  
  c1->send( "Hi!" );
  c3->send( "Hello!" );
  
  delete mediator;
  return 0;
}

三、优缺点

优点

  • 简化了对象之间的交互。
  • 将各同事解耦。
  • 减少子类生成。
  • 可以简化各同事类的设计和实现。

缺点

  • 在具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。

四、适用环境

  • 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
  • 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象。
  • 交互的公共行为,如果需要改变行为则可以增加新的中介者类。

五、模式应用

MVC架构中控制器,Controller作为一种中介者,它负责控制视图对象View和模型对象Model之间的交互。如在Struts中,Action就可以作为JSP页面与业务对象之间的中介者。

六、模式扩展

  • 中介者模式可以方便地应用于图形界面(GUI)开发中,在比较复杂的界面中可能存在多个界面组件之间的交互关系。
  • 对于这些复杂的交互关系,有时候我们可以引入一个中介者类,将这些交互的组件作为具体的同事类,将它们之间的引用和控制关系交由中介者负责,在一定程度上简化系统的交互,这也是中介者模式的常见应用之一。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值