应用场景

  • 系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象
  • 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类

中介者模式

定义

包装了一系列对象相互作用的方式,使得这些对象不必互相明显引用,从而使得他们比较松散的耦合

设计原则:迪米特法则

意图

使用一个中介对象来封装一系列的对象交互,中介者使得这些对象不必互相明显引用,从而使得他们比较松散的耦合,而且可以独立的改变他们之间的交互

主要解决问题

系统的对象与对象之间存在大量的关联,这样就会导致系统的结构变的复杂,如果一个对象发生了改变,就需要跟踪与其关联的对象

何时使用

多个类相互耦合,形成了网状结构,要把网状结构变成星状结构

网状结构:



这些对象即会影响别的对象,又会被别的对象影响,因此常常叫做同事对象,从图中可以看出,几乎每一个对象都和其他对象发生相互作用,这是一个过度耦合的系统

星状结构:



通过引入中介者对象,可以把系统的网状结构变成星状结构,可以看出,同事对象之间不再通过直接的联系与其他对象发生关系,中介者对象的存在保证了对象结构上的稳定,也就是说,系统不会因为新对象的引入而造成大量的修改工作

优缺点

优点:

  • 降低了类的复杂度,将一对多转化成了一对一
  • 各个类之间解耦了
  • 符合设计原则:迪米特法则

缺点:

  • 增加了中介者类的复杂度

结构图:



涉及的角色:

  • 抽象中介者(Mediator)角色:定义出同事对象到中介者对象的接口,其中主要的方法是一个或者多个事件方法,这个角色一般是有一个Java抽象类或者Java对象实现
  • 具体中介者(ConcreteMediator)角色:实现了抽象中介者角色所声明的事件方法,具体中介者角色知晓所有的具体同事类,它从具体同事类接收消息、向具体同事对象发出命令,一般是由一个具体Java类实现
  • 抽象同事类(Colleague)角色:定义出中介者到同事对象的接口,同事对象只知道中介者而不知道其他的同事对象
  • 具体同事类(ConcreteColleague)角色:每一个具体同事类都知道它自己在小范围的行为,而不知道它在大范围的目的

对应源码如下:

public abstract class Mediator {

    /** 事件方法,由子类实现 */
public abstract void colleagueChanged(Colleague colleague); public static void main(String[] args) {
ConcreteMediator mediator = new ConcreteMediator();
mediator.create();
Colleague colleague1 = new Colleague1(mediator);
Colleague colleague2 = new Colleague2(mediator);
mediator.colleagueChanged(colleague1);
}
}
public class ConcreteMediator extends Mediator {

    private Colleague1 colleague1;

    private Colleague2 colleague2;

    @Override
public void colleagueChanged(Colleague colleague) {
colleague1.action();
colleague2.action();
} /** 创建同事对象 */
public void create() {
colleague1 = new Colleague1(this);
colleague2 = new Colleague2(this);
} /** 提供同事对象 */
public Colleague1 getColleague1() {
return colleague1;
} /** 提供同事对象 */
public Colleague2 getColleague2() {
return colleague2;
}
}
public abstract class Colleague {

    private Mediator mediator;

    /** 参量:中介者对象 */
public Colleague(Mediator mediator) {
this.mediator = mediator;
} /** 取值方法 */
public Mediator getMediator() {
return mediator;
} /** 行动方法,由子类实现 */
public abstract void action(); /** 可以改变对象的内部状态 */
public void change() {
mediator.colleagueChanged(this);
}
}
public class ConcreteColleague extends Colleague {
/**
* 参量:中介者对象
*
* @param mediator
*/
public ConcreteColleague(Mediator mediator) {
super(mediator);
} @Override
public void action() {
System.out.println("实现了行动方法");
}
}

世界贸易组织WTO

世界贸易组织(英语:World Trade Organization),简称世贸组织(WTO),是一个独立于联合国的永久性国际组织。世界贸易组织的职能是调解纷争加入WTO不算签订一种多边贸易协议。它是贸易体制的组织基础和法律基础,还是众多贸易协定的管理者、各成员贸易立法的监督者、以及为贸易提供解决争端和进行谈判的场所

比如在没有WTO的时候,各个国家之间的贸易往来是这样的:



有了WTO之后,贸易往来变成了下图所示:



小场景:

中国、法国、韩国三个国家需要通过WTO进行贸易往来,中国的茶叶需要出口到法国和韩国,法国的鹅肝需要出口到中国和韩国,而韩国的泡菜也需要出口到中国和法国

WTO组织,即抽象中介者:

定义了两个接口,加入WTO和贸易往来:

public interface WTOMediator {

    /** 加入WTO */
void addWTO(Countries countries); /** 贸易往来 */
void trade(Countries countries);
}

具体中介者,实现了上面的接口,定义了如何加入WTO和如何进行贸易往来:

public class ConcreteWTOMediator implements WTOMediator {

    private List<Countries> countriesList = new ArrayList<>();

    @Override
public void addWTO(Countries countries) {
if (!countriesList.contains(countries)) {
countries.setWtoMediator(this);
this.countriesList.add(countries);
} } @Override
public void trade(Countries countries) {
countriesList.forEach(v -> {
if(!v.equals(countries)) {
v.receive();
}
}); }
}

抽象同事类,知道WTO的存在,但是不知道其他国家的存在:

public abstract class Countries {

    public WTOMediator wtoMediator;

    /** 贸易进口 */
public abstract void receive(); /** 贸易出口 */
public abstract void send(); public void setWtoMediator(WTOMediator wtoMediator) {
this.wtoMediator = wtoMediator;
}
}

中国、法国、韩国各个国家需要实现上面的接口:

public class China extends Countries {

    @Override
public void receive() {
System.out.println("贸易出口到中国");
} @Override
public void send() {
System.out.println("中国茶叶出口了!");
this.wtoMediator.trade(this);
}
}
public class French extends Countries {

    @Override
public void receive() {
System.out.println("贸易出口到法国");
} @Override
public void send() {
System.out.println("法国鹅肝出口了!");
this.wtoMediator.trade(this);
}
}
public class Korea extends Countries {

    @Override
public void receive() {
System.out.println("贸易出口到韩国");
} @Override
public void send() {
System.out.println("韩国泡菜出口了!");
this.wtoMediator.trade(this);
}
}

下面是测试类,即开始进行贸易往来了:

public class Test {
public static void main(String[] args) {
//构建WTO中介者
WTOMediator mediator = new ConcreteWTOMediator(); //构建具体的同事类,即各个国家
Countries china = new China();
Countries french = new French();
Countries korea = new Korea(); //加入WTO
mediator.addWTO(china);
mediator.addWTO(french);
mediator.addWTO(korea); china.send();
System.out.println();
french.send();
System.out.println();
korea.send();
}
}



类图:



注意事项:

  • 不应当在职责划分混乱的时候使用中介者模式
  • 不应当对数据类和方法类使用
  • 需要正确的理解封装

与中介者模式有关的设计模式:

  • 外观模式
  • 观察者模式
  • 适配器模式

请看完上面四个模式后思考,它们的异同在哪里

从中国加入WTO来看Java设计模式:中介者模式的更多相关文章

  1. JAVA 设计模式 中介者模式

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

  2. Java设计模式----中介者模式

    说到中介大家都不会陌生,买房子租房子有中介,出国留学有中介,买卖二手车还是有中介.那么中介到底是个什么角色呢?实际上,中介就是让买卖双方不必面对面直接交流,由他/她来完成买卖双方的交易,达到解耦买卖人 ...

  3. Java设计模式-中介者模式(Mediator)

    中介者模式也是用来降低类类之间的耦合的,因为如果类类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改.如果使用中介者模式,只需关心和Mediator类的关系 ...

  4. Java设计模式—中介者模式

    中介者模式是一种并不常用的模式,在此简单阐述阐述. 定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 类型:行为类模式 ...

  5. Tony老师带你来看Java设计模式:代理模式

    目录 定义 作用 意图 主要解决问题 优缺点 与装饰者模式的区别 结构 从Tony老师来看实现方式 静态代理 动态代理 JDK动态代理的实现 cglib动态代理的实现 定义 为其他对象提供一种代理来控 ...

  6. 从西天取经的九九八十一难来看Java设计模式:模板方法模式

    目录 示例 模板方法模式 定义 意图 主要解决问题 适用场景 优缺点 西天取经的九九八十一难 示例 当我们设计一个类时,我们能明确它对外提供的某个方法的内部执行步骤, 但一些步骤,不同的子类有不同的行 ...

  7. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  8. Java设计模式之builder模式

    Java设计模式之builder模式 今天学mybatis的时候,知道了SQLSessionFactory使用的是builder模式来生成的.再次整理一下什么是builder模式以及应用场景. 1. ...

  9. java设计模式6——代理模式

    java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...

随机推荐

  1. sql语句的练习,已练习的会以绿色标注!!!

    表架构 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师 ...

  2. 🤔 移动端 JS 引擎哪家强?美国硅谷找......

    如果你喜欢我写的文章,可以把我的公众号设为星标 ,这样每次有更新就可以及时推送给你啦 在一般的移动端开发场景中,每次更新应用功能都是通过 Native 语言开发并通过应用市场版本分发来实现的.但是市场 ...

  3. vue3与vue2的区别

    全局属性 vue2 对于一些第三方插件,vue2中通常使用prototype原型来挂载到vue对象中 import Vue from 'vue' Vue.prototype.$http=Axiox V ...

  4. BurpSuite生成快捷方式

    Win下 在win系统写个脚本,能方便快捷的打开burp. burp.bat @echo oFF if "%1" neq "1" ( >"%te ...

  5. 面试题-python 如何读取一个大于 10G 的txt文件?

    前言 用python 读取一个大于10G 的文件,自己电脑只有8G内存,一运行就报内存溢出:MemoryError python 如何用open函数读取大文件呢? 读取大文件 首先可以自己先制作一个大 ...

  6. CCF(压缩编码):动态规划+平行四边形优化

    压缩编码 201612-4 一开始看这题还以为是哈夫曼编码的题目,结果是哈夫曼题目的变形. 哈夫曼编码是每次合并任意两堆石子,而这里的题目是合并相邻的两堆石子,而且这里的合并花费是合并两堆石子加上所有 ...

  7. Bullet碰撞检测

    DBVT 在bullet 引擎中是很基础且重要的一个数据结构,本质上是一个可以动态更新的AABB树. 碰撞响应的分析 约束分类:可积约束,不可积约束 ,摩擦力(见[1]第四章) 整个bullet在动力 ...

  8. [UNP] IO 复用

    UNP Part-2: Chapter 6. I/O Multiplexing: The select and poll Functions 的读书笔记. 在 这篇博客 的最后,我们对文章中的服务器- ...

  9. MySQL日志收集之Filebeat和Logstsh的一键安装配置(ELK架构)

    关于ELK是什么.做什么用,我们不在此讨论.本文重点在如何实现快速方便地安装logstash和filebeat组件,特别是在近千台DB Server的环境下(为了安全保守,公司DB Server 目前 ...

  10. (数据科学学习手札112)Python+Dash快速web应用开发——表单控件篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...