基本需求

  • 智能家庭包括各种设备,闹钟、咖啡机、电视机、窗帘等
  • 要看电视时,各个设备可以协同工作,自动完成看电视的准备工作,比如流程为:闹铃响起->咖啡机开始做咖啡->窗帘自动落下->电视机开始播放

传统方案

  • 各个类之间相互调用,依赖严重,消息传递不准确,调用结构混乱
  • 说明
    • 当各电器对象有多种状态改变时,相互之间的调用关系会比较复杂
    • 各个 电器对象彼此联系,你中有我,我中有你,不利于松耦合
    • 各个电器对象之间所传递的消息(参数),容易混乱
    • 当系统增加一个新的电器对象时,或者执行流程改变时,代码的可维护性、扩展性都不理想 考虑中介者模式

基本介绍

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

  • 中介者模式属于行为型模式,使代码易于维护

  • 比如MVC模式,C(Controller 控制器)是M(Model 模型)和V(View 视图)的中介者,在前后端交互时起到了中间人的作用

  • 比如租房子

    • 没有中介:有六个房东需要出租房屋,适合不一样的人租住。这六个房东之间有点联系。这时租客来租房,看了一号房东的房子不满意、但是一号房东觉得可以让他去看看其他五个朋友的房间。然后开始联系五个朋友。进行消息传递。一个如此,另外五个亦如此,如果二号房东房屋不出租或者出租出去了,情况发生了变化。他则需要通知其他五个朋友,告诉他们不用再给他介绍租客。这里就造成了中间一个人发生了变化,需要改动其他五个人
    • 有中介:那六个房东都把房屋交给中介处理。租客A看房间一不满意直接通过中介看房间二。当房间二被出租了。中介也只需要通知房东二号、然后他们签订合同。下次还有人看房间就不会再看房间二。这里一个出现了变化也就影响改变了一个。并不会影响其他另外五个房东
  • UML类图(原理)

    • 说明
      • Mediator 就是抽象中介者,定义了同事对象到中介者对象的接口
      • Colleague 是抽象同事类
      • ConcreteMediator 具体的中介者对象, 实现抽象方法, 他需要知道所有的具体的同事类,即以一个集合来管理HashMap,并接受某个同事对象消息,完成相应的任务
      • ConcreteColleague 具体的同事类,会有很多, 每个同事只知道自己的行为,而不了解其他同事类的行为(方法),但是他们都依赖中介者对象
  • UML类图(案例)

    • 说明
      • ConcreteMediator是中介者实现类
      • 在创建同事实现类的时候通过其构造方法将其注册到中介者中,通过sendMessage方法向中介者发送消息
      • ConcreteMediator的getMessage方法会接收到同事类的消息协调调用其他对象,是核心方法
  • 代码实现

    • public abstract class Mediator {
      
         // 中介者抽象类
      
         // 将同事类加入到中介者中,由中介者对所有同事类进行交互,同事类之间不进行交互
      // 将依赖由网状变成星状
      public abstract void register(String colleagueName, Colleague colleague); // 接收消息 由同事类发出
      public abstract void getMessage(String colleagueName, int stateChange); // 发送消息,发给同事类,本次案例中没有用到
      public abstract void sendMessage(); } // 中介者实现类
      public class ConcreteMediator extends Mediator { // 使用集合管理所有的中介者,如果key重复,则是最新注册的 ,可否弄成MapList的形式管理重复key
      private Map<String, Colleague> colleagueMap; // 名称的集合,方便我们自己获取对应的同事类,因为每次注册时 我们并不知道key,想获取value时不能获取,指定名称 后续使用简单
      private Map<String, String> nameMap; public ConcreteMediator() {
      this.colleagueMap = new HashMap<>();
      this.nameMap = new HashMap<>();
      } @Override
      public void register(String colleagueName, Colleague colleague) {
      colleagueMap.put(colleagueName, colleague);
      if (colleague instanceof Alarm) {
      // 自定义名称 方便我们下面使用
      nameMap.put("alarm", colleagueName);
      } else if (colleague instanceof CoffeeMachine) {
      nameMap.put("coffeeMachine", colleagueName);
      } else if (colleague instanceof Curtain) {
      nameMap.put("curtain", colleagueName);
      } else if (colleague instanceof TV) {
      nameMap.put("tv", colleagueName);
      }
      } @Override
      public void getMessage(String colleagueName, int stateChange) {
      // 根据得到消息,完成对应任务,中介者在这个方法,协调各个具体的同事对象,完成任务
      if (colleagueMap.get(colleagueName) instanceof Alarm) {
      // 处理闹钟的消息 可使用中介者的sendMessage方法进行处理
      if (stateChange == 0) {
      ((CoffeeMachine) colleagueMap.get(nameMap.get("coffeeMachine"))).startCoffee();
      ((TV) colleagueMap.get(nameMap.get("tv"))).startTv();
      } else if (stateChange == 1) {
      ((TV) colleagueMap.get(nameMap.get("tv"))).stopTv();
      }
      } else if (colleagueMap.get(colleagueName) instanceof CoffeeMachine) {
      // 处理咖啡机的消息
      if (stateChange == 0) {
      ((Curtain) colleagueMap.get(nameMap.get("curtain"))).upCurtains();
      }
      } else if (colleagueMap.get(colleagueName) instanceof Curtain) {
      // 处理窗帘的消息
      System.out.println();
      } else if (colleagueMap.get(colleagueName) instanceof TV) {
      // 处理电视机的消息
      System.out.println();
      }
      } @Override
      public void sendMessage() { }
      }
    • public abstract class Colleague {
      
         // 同事抽象类
      
         protected String name;
      
         private Mediator mediator;
      
         public Colleague(String name, Mediator mediator) {
      this.name = name;
      this.mediator = mediator;
      } public Mediator getMediator() {
      return this.mediator;
      } // 发送消息
      public abstract void sendMessage(int stateChange); } // 同事子类一 闹钟类
      public class Alarm extends Colleague { public Alarm(String name, Mediator mediator) {
      super(name, mediator);
      // 将自己在中介者中进行注册
      mediator.register(name, this);
      } @Override
      public void sendMessage(int stateChange) {
      // 获取中介者 调用中介者的getMessage方法 将消息传递给中介者 由中介者处理消息
      this.getMediator().getMessage(super.name, stateChange);
      } public void sendAlarm(int stateChange) {
      sendMessage(stateChange);
      }
      } // 同事子类二 咖啡机
      public class CoffeeMachine extends Colleague { public CoffeeMachine(String name, Mediator mediator) {
      super(name, mediator);
      mediator.register(name, this);
      } @Override
      public void sendMessage(int stateChange) {
      this.getMediator().getMessage(super.name, stateChange);
      } public void startCoffee() {
      System.out.println("It's time to startcoffee!");
      } public void finishCoffee() {
      System.out.println("After 5 minutes!");
      System.out.println("Coffee is ok!");
      sendMessage(0);
      }
      } // 同事子类三 窗帘
      public class Curtain extends Colleague { public Curtain(String name, Mediator mediator) {
      super(name, mediator);
      mediator.register(name, this);
      } @Override
      public void sendMessage(int stateChange) {
      this.getMediator().getMessage(super.name, stateChange);
      } public void upCurtains() {
      System.out.println("I am holding Up Curtains!");
      }
      } // 同事子类四 电视机
      public class TV extends Colleague { public TV(String name, Mediator mediator) {
      super(name, mediator);
      mediator.register(name, this);
      } @Override
      public void sendMessage(int stateChange) {
      this.getMediator().getMessage(super.name, stateChange);
      } public void startTv() {
      System.out.println("It's time to StartTv!");
      } public void stopTv() {
      System.out.println("Stop Tv!");
      }
      }

注意事项

  • 多个类相互耦合,会形成网状结构, 使用中介者模式将网状结构分离为星型结构,进行解耦
  • 如果增加一个同事类,直接增加即可,降低了类的复杂度,将一对多转化成了一对一
  • 减少类间依赖,降低了耦合,符合迪米特原则
  • 中介者承担了较多的责任,一旦中介者出现了问题,整个系统就会受到影响
  • 中介者 承担了较多的责任,一旦中介者出现了问题,整个系统就会受到影响

18.java设计模式之中介者模式的更多相关文章

  1. 折腾Java设计模式之中介者模式

    博文原址:折腾Java设计模式之中介者模式 中介者模式 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性.这种模式提供了一个中介类,该类通常处理不同类之间的通信,并 ...

  2. 从中国加入WTO来看Java设计模式:中介者模式

    目录 应用场景 中介者模式 定义 意图 主要解决问题 何时使用 优缺点 世界贸易组织WTO 应用场景 系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象 想通过一个 ...

  3. Java 设计模式之中介者模式

    本文继续23种设计模式系列之中介者模式.   定义 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互.   角色 抽象中介者: ...

  4. java设计模式之中介者模式

    中介者模式 用一个中介对象来封装一系列的对象交互.中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 中介者模式UML图 中介者模式代码 package com ...

  5. Java 设计模式 之 中介者模式(Mediator)

    中介者的功能非常简单,就是封装对象之间的交互. 如果一个对象的操作会引起其他相关对象的变化,或者是某个操作需要引起其他对象的后续或连带操作,而这个对象又不希望自己来处理这些关系,那么久可以找中介者,把 ...

  6. Java设计模式之《代理模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6525527.html 代理模式算是我接触较早的模式,代理就是中介,中间人.法律上也有代理, ...

  7. Java设计模式之工厂方法模式(转) 实现是抽象工厂?

    Java设计模式之工厂方法模式 责任编辑:覃里作者:Java研究组织   2009-02-25   来源:IT168网站   文本Tag: 设计模式 Java [IT168 技术文章]         ...

  8. Java设计模式 - - 单例模式 装饰者模式

    Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...

  9. 重学 Java 设计模式:实战桥接模式(多支付渠道「微信、支付宝」与多支付模式「刷脸、指纹」场景)

    作者:小傅哥 博客:https://bugstack.cn - 编写系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么你的代码那么多ifelse 同类的业务.同样的功能, ...

随机推荐

  1. TortoiseGit和intellij idea配置秘钥

    第一:intellij idea 配置gitlab ssh key 1:打开git bash,不需要进入任何目录,直接输入 ssh-keygen -t rsa 一路回车 2:生成之后找到秘钥文件id_ ...

  2. win32 C++制作美观按钮,告别win32 API编程中默认的灰色按钮

    使用win32 API制作美观按钮,当鼠标移入/移出按钮时改变按钮背景颜色,类似HTML网页中的效果,告别win32 API编程中默认的灰色按钮,效果图见下面动图和视频. 下载地址: 按钮效果(win ...

  3. 博流BL602&BL604开发板介绍

    在2020松山湖论坛上,博流智能科技(南京)有限公司销售副总裁刘占领介绍了基于RISC-V核的低功耗.高可靠Wi-Fi+BLE二合一SoC芯片BL602.主要应用领域包括人工智能与工业互联网,特别是电 ...

  4. STL——容器(Set & multiset)的默认构造 & 带参构造 & 对象的拷贝构造与赋值

    1. 默认构造 set<int> setInt;              //一个存放int的set容器. set<float> setFloat;          //一 ...

  5. 下载windows官网镜像并打包成iso文件

    一.微软官网下载镜像地址:https://www.microsoft.com/zh-cn/software-download/ 选择所需下载的win10.win7等windows镜像(以win10为例 ...

  6. 仵航说 Vue项目如何打包并发布到linux服务器 仵老大

    1,打包 1.1首先你会在本地编辑好你的代码, 1.2然后在控制台输入 npm run build npm run build 1.3稍等片刻就打包完毕 2,位置 2.1打包完毕之后会在项目中生成一个 ...

  7. Yii2 给表添加字段后报错 Getting unknown property

    手动在数据库中添加了image字段 然后再模型类Image中的 rule方法也将image的验证规则放进去了 但是在 $model = new Image 后,使用$model->iamge 还 ...

  8. Python基础编程——数据类型

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 在程序设计和编程中,会涉及到各种各样的数据类型,而不同的数据类型变量之间可以进行的运算是不同的.在p ...

  9. C#使用时间戳

    前言 参考博客 C#获取和转换时间戳: https://blog.csdn.net/weixin_39885282/article/details/79462443 获取时间戳: https://ww ...

  10. Core3.0路由配置

    前言 MSDN文档,对ASP.NETCore中的路由完整的介绍 https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/routing?vi ...