当前位置: 首页 > news >正文

设计模式之中介者模式详解(Mediator Pattern)

在现实生活中,常常会出现好多对象之间存在复杂的交互关系,这种交互关系常常是“网状结构”,它要求每个对象都必须知道它需要交互的对象。例如,每个人必须记住他(她)所有朋友的电话;而且,朋友中如果有人的电话修改了,他(她)必须告诉其他所有的朋友修改,这叫作“牵一发而动全身”,非常复杂。

如果把这种“网状结构”改为“星形结构”的话,将大大降低它们之间的“耦合性”,这时只要找一个“中介者”就可以了。如前面所说的“每个人必须记住所有朋友电话”的问题,只要在网上建立一个每个朋友都可以访问的“通信录”就解决了。这样的例子还有很多,例如,你刚刚参力口工作想租房,可以找“房屋中介”;或者,自己刚刚到一个陌生城市找工作,可以找“人才交流中心”帮忙。

在软件的开发过程中,这样的例子也很多,例如,在 MVC 框架中,控制器(C)就是模型(M)和视图(V)的中介者;还有大家常用的 QQ 聊天程序的“中介者”是 QQ 服务器。所有这些,都可以采用“中介者模式”来实现,它将大大降低对象之间的耦合性,提高系统的灵活性

认识中介者模式

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

中介者模式是一种对象行为型模式,其主要优点是:

  1. 松散耦合、将多个对象之间的联系紧耦合封装到中介对象中,做到松耦合。不会导致一动牵全身。

  2. 将多个对象之间的交互联系集中在中介对象中。发送变化仅需修改中介对象即可、提供系统的灵活性、使同事对象独立而易于复用。

  3. 符合迪米特原则。就是说一个对象应当对其他对象有尽可能少的了解。减少各个对象之间的了解。

其主要缺点是:
当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。

原理类图与角色说明

中介者模式的原理类图

角色说明

  • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
  • 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  • 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
  • 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

模式应用场景

  1. 系统中对象间存在较为复杂引用,导致依赖关系和结构混乱而无法复用的情况。

  2. 想通过一个中间类来封装多个类的行为,但是又不想要太多的子类。

应用实例

下面以房产中介为实例应用中介者模式:

创建抽象中介者(Mediator):中介接口
//抽象中介者:中介公司
public interface Medium {
    void register(Customer member);//客户注册
    void relay(String from,String ad);//转发
}
创建具体中介者(ConcreteMediator):房产中介
//具体中介者,房产中介公司
public class EstateMedium implements Medium {
    List<Customer> members = new ArrayList<Customer>();

    @Override
    public void register(Customer member) {
        if (!members.contains(member)) {
            members.add(member);
            member.setMedium(this);
        }
    }

    @Override
    public void relay(String from, String ad) {
        for (Customer ob : members) {
            String name = ob.getName();
            //非自己
            if (!name.equals(from)) {
                ob.receive(from,ad);
            }
        }
    }
}
创建抽象同事类(Colleague):客户
//抽象同事类:客户
public abstract class Customer {
    protected String name;
    protected Medium medium;
    public Customer(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setMedium(Medium medium) {
        this.medium = medium;
    }

    public abstract void send(String ad);
    public abstract void receive(String from,String ad);
}
创建具体同事类(Concrete Colleague):买方与卖方
//具体同事类:卖方
public class Seller extends Customer {

    public Seller(String name) {
        super(name);
    }
    @Override
    public void send(String ad) {
        System.out.println(getName()+"发送信息: " + ad);
        medium.relay(name,ad);
    }

    @Override
    public void receive(String from, String ad) {
        System.out.println(getName()+"收到来自"+from + "的信息:" + ad);
    }
}
//具体同事类:买方
public class Buyer extends Customer {
    public Buyer(String name) {
        super(name);
    }
    @Override
    public void send(String ad) {
        System.out.println(getName()+"发送信息: " + ad);
        medium.relay(name,ad);
    }

    @Override
    public void receive(String from, String ad) {
        System.out.println(getName()+"收到来自"+from + "的信息:" + ad);
    }
}
客户端调用测试
public class Client {
    public static void main(String[] args) {
        Medium md=new EstateMedium();    //房产中介
        Customer seller,buyer;
        seller=new Seller("张三(卖方)");
        buyer=new Buyer("李四(买方)");
        md.register(seller); //客户注册
        md.register(buyer);
        seller.send("我有一套房子");
        buyer.send("有两室一厅的吗?");
        seller.send("有");
    }
}
输出结果如下
张三(卖方)发送信息: 我有一套房子
李四(买方)收到来自张三(卖方)的信息:我有一套房子
李四(买方)发送信息: 有两室一厅的吗?
张三(卖方)收到来自李四(买方)的信息:有两室一厅的吗?
张三(卖方)发送信息: 有
李四(买方)收到来自张三(卖方)的信息:有

补充理解

关于租房中介的例子。假如没有租房中介。这里有六个房东需要出租房屋,房屋各不相同、各有各的特点、适合不一样的人租住。

这六个房东之间刚好有点联系。然后都在出租房屋。这时租客A来租房,看了一号房东的房子不满意、但是一号房东觉得可以让他去看看其他五个朋友的房间。然后开始联系他的五个朋友。这样运行下去好像有是没有什么问题的。但是其中二号房东如果房屋不出租或者出租出去了。也就是发生了变化。这是他则需要通知其他五个朋友,告诉他们不用再给他介绍租客了。这里就造成了中间一个人发生了变化,需要改动其他五个人。

那么如何可以解决这种情况呢。我们回到现在。把中介加进来、那六个房东都把房屋交给中介处理。租客A看房间一不满意直接通过中介看房间二。当房间二被出租了。中介也只需要通知房东二号、然后他们签订合同。下次还有人看房间就不会再看房间二了。这里一个出现了变化也就影响改变了一个。并不会影响其他另外五个房东。这个例子可以更好的帮助我们理解中介者模式。我们下面看两幅图。

图一:不采用中介的房东租房模式,多对多的网格。一动牵全身
在这里插入图片描述
图二:采用中介的租房模式,一对多、一个变动不影响其他
在这里插入图片描述
显然可以看出图二的“星状结构”更为简单明了,各个对象不需要显式地相互引用,从而使其耦合松散,任何一个都可以发生独立改变,也不会影响到其他对象。

参考

中介者模式(详解版)
通俗易懂设计模式解析——中介者模式

相关文章:

  • ASP.NET中利用存储过程实现模糊查询
  • 设计模式之备忘录模式详解(Memento Pattern)
  • 从asp转asp.net的相关
  • 设计模式之状态模式详解(State Pattern)
  • 浅谈DataSet 的用法
  • 多维数组和矩阵之顺时针打印二维数组
  • 各种数据库连接代码(JSP)
  • 多维数组与矩阵之0所在的行列清零
  • 多维数组与矩阵之之字形打印矩阵
  • 生姜有味的调色板
  • 设计模式之策略者模式详解(Strategy Pattern)
  • 利用J2ME里的RMS对记录进行排序
  • 设计模式之职责链(责任链)模式(ResponsibilityChain Pattern)
  • SWT GC的drawLine方法的一个隐藏Bug
  • 多维数组与矩阵之子数组的最大累加和
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • Android组件 - 收藏集 - 掘金
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • JS+CSS实现数字滚动
  • Mocha测试初探
  • overflow: hidden IE7无效
  • React as a UI Runtime(五、列表)
  • React Native移动开发实战-3-实现页面间的数据传递
  • Transformer-XL: Unleashing the Potential of Attention Models
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 翻译:Hystrix - How To Use
  • 简单基于spring的redis配置(单机和集群模式)
  • 排序算法之--选择排序
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 网页视频流m3u8/ts视频下载
  • 写给高年级小学生看的《Bash 指南》
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 【云吞铺子】性能抖动剖析(二)
  • NLPIR智能语义技术让大数据挖掘更简单
  • 阿里云服务器如何修改远程端口?
  • #13 yum、编译安装与sed命令的使用
  • #162 (Div. 2)
  • (02)Hive SQL编译成MapReduce任务的过程
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (3)llvm ir转换过程
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (搬运以学习)flask 上下文的实现
  • (翻译)terry crowley: 写给程序员
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (四) Graphivz 颜色选择
  • (转)Unity3DUnity3D在android下调试
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET Core 项目指定SDK版本
  • .net 无限分类