前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >中介者模式,说一说贝壳找房

中介者模式,说一说贝壳找房

作者头像
用户6557940
发布2022-07-24 15:57:56
5060
发布2022-07-24 15:57:56
举报
文章被收录于专栏:Jungle笔记

引言

离开学校参加工作之前,你一定是有一段时间是在找租,Jungle也是如此。

Jungle为了找到合适的房子,沿着地铁线一个小区一个小区的去问门卫问保安,或者照着小区门口展板上的房东的联系方式去找房东……此事已经过去大半年了,但Jungle现在想来还是觉得很麻烦!麻烦在哪里?得亲自走亲自联系各个房东,通信录和微信得加好多房东……

其实有更省事的办法,那就是找中介,租房中介哪儿都是。虽然贵(主要原因),但是的确为租客省了很多事,其实也为房东省了很多事。

01

中介者模式简介

上述Jungle租房的例子如上图,如果Jungle自己去租房,得和各个房东亲自交互,如果另一个租客贱萌兔也在自己找房,同样也得和很多房东打交道。房东也是一样,得和众多不同的租客联系。如果有中介者了,房东们只需要去中介者那里注册一下,自己的房子在哪儿、什么户型设施、价格多少,就ok了;Jungle和贱萌兔也只需要和一个人打交道,那就是中介。中介的出现使两边都省去了不少事

软件设计模式中,也有一种类似的解决方案,那就是中介者模式——

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

如果一个系统里各个对象之间存在多对多的相互关系,可以将对象之间的一些交互行为从各个对象中分离出来,集中封装在一个中介者对象中,使其耦合松散,并由中介者统一协调。通过中介者,对象之间的多对多关系就简化了相对更简单的一对多关系。

02

中介者模式结构

中介者模式的UML图如下,为了便于扩展,系统引入了抽象中介者。

由图可知,中介者模式主要有以下角色:

  • Mediator(抽象中介者):声明一个用于与各个同事对象之间交互的接口,通常声明一个注册方法,用于增加同事对象;
  • ConcreteMediator(具体中介者):实现上面的接口,协调各个同事对象来实现协作行为,维持对各个同事对象的引用;
  • Colleague(抽象同事类):声明各个同事类公有的接口,同时维持了一个对抽象中介者类的引用;
  • ConcreteColleague(具体同事类):具体实现接口,具体同事类只需与中介者通信,通过中介者完成与其他同事类的通信。

中介者模式的核心在于引入了中介者类,中介者类承担了两个层次的职责:

  • 结构上起中转作用:通过中介者的中转,各个同事之间不必再相互显示调用或引用,只需通过中介者实现间接调用的目的;
  • 行为上起协调作用:中介者可以进一步地将同事之间的关系进行封装,同事可以一致地和中介者进行交互,而不必指出中介者具体该如何操作,中介者根据封装在自身内部的协调逻辑对同事的请求进一步处理,将同事成员之间的关系行为进行分离和封装。

03

中介者模式代码实例

本节Jungle将采用中介者模式模拟“租客——房租中介——房东”之间的爱恨情仇!(本例的代码相对较复杂,具体代码资源请见https://github.com/FengJungle/DesignPattern)

Jungle和贱萌兔想要通过房屋中介(Agency)租房,需要去中介处了解房东(Landlord)的信息(姓名,价格,地址和联系方式);房东们(Landlord)需要在中介处注册自己的房源,同时也可以从中介处了解租客(Tenant)的信息(姓名)。

本例的UML图如下:

3.0.公共头文件

为区分房东和租客,Jungle定义了一个枚举类型和对应的setter、getter方法:

代码语言:javascript
复制
#ifndef __COMMON_H__
#define __COMMON_H__

// 公共头文件

#include <vector>
using namespace std;

enum PERSON_TYPE
{
  NONE_PERSON,
  LANDLORD,
  TENANT
};

#endif  //__COMMON_H__

3.1.中介者

3.1.1.抽象中介者

代码语言:javascript
复制
// 抽象中介者
class Mediator
{
public:
  Mediator(){}
  // 声明抽象方法
  virtual void operation(Colleague*) = 0;
  // 声明注册方法
  virtual void registerMethod(Colleague*) = 0;
};

3.1.2.具体中介者Agency

具体中介者就是真实的中介对象类,他手里有房东的名单(landlordList)和租客名单(tenantList),房东和租客通过registerMethod()在中介处登记注册。同时,房东可以询问中介租客信息,租客也可以向中介询问房东信息。

代码语言:javascript
复制
// 具体中介者
class Agency:public Mediator
{
public:
  Agency(){}
  void registerMethod(Colleague* person){
    switch (person->getPersonType()){
    case LANDLORD:
      landlordList.push_back((Landlord*)person);
      break;
    case TENANT:
      tenantList.push_back((Tenant*)person);
      break;
    default:
      printf("wrong person\n");
    }
  }
  void operation(Colleague* person){
    switch (person->getPersonType()){
    case LANDLORD:
      for (int i = 0; i < tenantList.size(); i++){
        tenantList[i]->answer();
      }
      break;
    case TENANT:
      for (int i = 0; i < landlordList.size(); i++){
        landlordList[i]->answer();
      }
      break;
    default:
      break;
    }
  }
private:
  vector<Landlord*>landlordList;
  vector<Tenant*>tenantList;
};

3.2.同事类

3.2.1.抽象同事类

代码语言:javascript
复制
// 前向声明
class Mediator;
class Agency;

// 抽象同事类
class Colleague
{
public:
  Colleague(){}
  void setMediator(Mediator* iMediator){
    this->mediator = iMediator;
  }
  Mediator* getMediator(){
    return this->mediator;
  }
  void setPersonType(PERSON_TYPE iPersonType){
    this->personType = iPersonType;
  }
  PERSON_TYPE getPersonType(){
    return this->personType;
  }
  virtual void ask() = 0;
  virtual void answer() = 0;
private:
  PERSON_TYPE personType;
  Mediator* mediator;
};

3.2.2.具体同事类——房东(Landlord)

声明:

代码语言:javascript
复制
// 具体同事类:房东
class Landlord :public Colleague
{
public:
  Landlord();
  Landlord(string iName, int iPrice, string iAddress, string iPhoneNum);
  void ask();
  void answer();
private:
  string name;
  int price;
  string address;
  string phoneNumber;
};

实现:

代码语言:javascript
复制
#include "Colleague.h"
#include "Mediator.h"

Landlord::Landlord(){
  name = "none";
  price = 0;
  address = "none";
  phoneNumber = "none";
  setPersonType(NONE_PERSON);
}

Landlord::Landlord(string iName, int iPrice, 
  string iAddress, string iPhoneNum){
  name = iName;
  price = iPrice;
  address = iAddress;
  phoneNumber = iPhoneNum;
  setPersonType(LANDLORD);
}

void Landlord::answer(){
  printf("房东姓名:%s, 房租:%d, 地址:%s, 联系电话:%s\n",
    name.c_str(), price, address.c_str(), phoneNumber.c_str());
}

void Landlord::ask(){
  printf("房东%s查看租客信息:\n",name.c_str());
  (this->getMediator())->operation(this);
}

3.2.3.具体同事类——租客(Tenant)

声明:

代码语言:javascript
复制
// 具体同事类:租客
class Tenant :public Colleague
{
public:
  Tenant();
  Tenant(string name);
  void ask();
  void answer();
private:
  string name;
};

实现

代码语言:javascript
复制
#include "Colleague.h"
#include "Mediator.h"

Tenant::Tenant(){
  name = "none";
  setPersonType(NONE_PERSON);
}

Tenant::Tenant(string iName){
  name = iName;
  setPersonType(TENANT);
}

void Tenant::ask(){
  printf("租客%s询问房东信息\n", name.c_str()); 
  (this->getMediator())->operation(this);
}

void Tenant::answer(){
  printf("租客姓名:%s\n", name.c_str());
}

3.3.客户端代码示例及效果

代码语言:javascript
复制
#include <iostream>
#include "Mediator.h"
#include "Colleague.h"

int main()
{
  // 创建租房中介
  Agency *mediator = new Agency();

  // 创建3位房东
  Landlord *fangdong1 = new Landlord("刘备", 1350, "成都市双流区", "1351025");
  Landlord *fangdong2 = new Landlord("关羽", 1500, "成都市武侯区", "1378390");
  Landlord *fangdong3 = new Landlord("张飞", 1000, "成都市龙泉驿", "1881166");
  fangdong1->setMediator(mediator);
  fangdong2->setMediator(mediator);
  fangdong3->setMediator(mediator);
  // 房东在中介处登记注册房源信息
  mediator->registerMethod(fangdong1);
  mediator->registerMethod(fangdong2);
  mediator->registerMethod(fangdong3);

  // 创建两位租客Jungle和贱萌兔
  Tenant *jungle = new Tenant("Jungle");
  Tenant *jianmengtu = new Tenant("贱萌兔");
  jungle->setMediator(mediator);
  jianmengtu->setMediator(mediator);
  // Jungle和贱萌兔在中介处登记求租信息
  mediator->registerMethod(jungle);
  mediator->registerMethod(jianmengtu);

  jungle->ask();
  printf("\n\n");
  fangdong1->ask();

  printf("\n\n");
  system("pause");
  return 0;
}

运行结果如下:

04

总结

优点:

  • 简化了对象之间的交互,通过中介者,对象之间的多对多关系就简化了相对更简单的一对多关系;
  • 可将各个同事对象解耦,利于各个同事之间的松散耦合,可独立地改变和复用每一个同事对象,增加新的中介者和同事都比较方便,符合开闭原则;
  • 可减少子类生成,将原本分布于多个对象之间的行为封装在一起,只需生成新的具体中介者类就可以改变这些行为。

缺点:

  • 具体中介者类中包含了大量与同事之间交互的细节和逻辑,可能使得中介者类很复杂以至于难以管理维护。

适用环境:

  • 系统中的对象之间存在复杂的交互关系,使得系统内逻辑错综复杂,难以管理;
  • 一个对象引用了其他很多对象,并直接和这些对象交互,导致该对象难以复用。

(本例的代码相对较复杂,具体代码资源请见https://github.com/FengJungle/DesignPattern)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Jungle笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3.0.公共头文件
  • 3.1.中介者
    • 3.1.1.抽象中介者
      • 3.1.2.具体中介者Agency
      • 3.2.同事类
        • 3.2.1.抽象同事类
        • 3.3.客户端代码示例及效果
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档