世界需要和平--中介者模式
1.1 世界需要和平
"你想呀,国与国之间的关系,就类似于不同的对象与对象之间的关系,这就要求对象之间需要知道其他所有对象,尽管将一个系统分割成许多对象通常可以增加其可复用性,但是对象间相互连接的激增又会降低其可复用性了。你知道为什么会这样?"
"我想是因为大量的连接使得一个对象不可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体,所以,对系统的行为进行任何较大的改动就十分困难了。"
"总结得很好嘛,要解决这样的问题,可以应用什么原则?"
"我记得之前讲过的叫'迪米特法则',如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。在这里,你的意思就是说,国与国之间完全可以通过'联合国'这个中介者来发生关系,而不用直接通信。"
"是呀,通过中介者对象,可以将系统的网状结构变成以中介者为中心的星状结构,每个具体对象不再通过直接的联系与另一个对象发生相互作用,而是通过'中介者'对象与另一个对象发生相互作用。中介者对象的设计,使得系统的结构不会因为新对象的引入造成大量的修改工作。"
"当时你对我解释'迪米特法则'的时候,是以我们公司的IT部门的管理为例子的,其实让我一个刚进公司的人去求任何一个不认识的IT部同事帮忙是有困难的,但如果是有IT主管来协调工作,就不至于发生我第一天上班却没有电脑进行工作的局面。IT主管就是一个'中介者'对象了。"
1.2 中介者模式
中介者模式(Mediator),用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。[DP]
中介者模式(Mediator)结构图
package code.chapter25.mediator0;public class Test {public static void main(String[] args) {System.out.println("**********************************************"); System.out.println("《大话设计模式》代码样例");System.out.println(); ConcreteMediator m = new ConcreteMediator();ConcreteColleague1 c1 = new ConcreteColleague1(m);ConcreteColleague2 c2 = new ConcreteColleague2(m);m.setColleague1(c1);m.setColleague2(c2);c1.send("吃过饭了吗?");c2.send("没有呢,你打算请客?");System.out.println();System.out.println("**********************************************");}
}//中介者类
abstract class Mediator{//定义一个抽象的发送消息方法,得到同事对象和发送信息public abstract void send(String message,Colleague colleague);
}abstract class Colleague {protected Mediator mediator;//构造方法,得到中介者对象public Colleague(Mediator mediator){this.mediator = mediator;}
}class ConcreteColleague1 extends Colleague {public ConcreteColleague1(Mediator mediator) {super(mediator);}public void send(String message) {this.mediator.send(message, this);}public void notify(String message) {System.out.println("同事1得到信息:" + message);}
}class ConcreteColleague2 extends Colleague {public ConcreteColleague2(Mediator mediator) {super(mediator);}public void send(String message){this.mediator.send(message, this);}public void notify(String message){System.out.println("同事2得到信息:" + message);}
}class ConcreteMediator extends Mediator{private ConcreteColleague1 colleague1;private ConcreteColleague2 colleague2;public void setColleague1(ConcreteColleague1 value) {this.colleague1 = value; }public void setColleague2(ConcreteColleague2 value) {this.colleague2 = value; }public void send(String message, Colleague colleague){if (colleague == colleague1) {colleague2.notify(message);}else {colleague1.notify(message);}}
}
"Colleague叫作抽象同事类,而ConcreteColleague是具体同事类,每个具体同事只知道自己的行为,而不了解其他同事类的情况,但他们却都认识中介者对象,Mediator是抽象中介者,定义了同事对象到中介者对象的接口,ConcreteMediator是具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接收消息,向具体同事对象发出命令。"
Colleague类:抽象同事类。
ConcreteColleague1和ConcreteColleague2等各种同事对象:
Mediator类:抽象中介者类。
ConcreteMediator类:具体中介者类。
"由于有了Mediator,使得ConcreteColleague1和ConcreteColleague2在发送消息和接收信息时其实是通过中介者来完成的,这就减少了它们之间的耦合度了。"大鸟说,"好了,该你来练习了,需求是美国和伊拉克之间的对话都是通过联合国安理会作为中介来完成。"
"哦,这应该没什么大问题,美国和伊拉克都是国家,有一个国家抽象类和两个具体国家类就可以了。但'联合国'到底是Mediator还是ConcreteMediator呢?"
"这要取决于未来是否有可能扩展中介者对象,比如你觉得联合国除了安理会,还有没有可能有其他机构存在呢?"
"联合国的机构还有如国际劳工组织、教科文组织、世界卫生组织、世界贸易组织等,很多的,所以Mediator应该是'联合国机构',而'安理会'是一个具体的中介者。"
"很好,如果不存在扩展情况,那么Mediator可以与ConcreteMediator合二为一。
1.3 安理会作中介
package code.chapter25.mediator1;public class Test {public static void main(String[] args) {System.out.println("**********************************************"); System.out.println("《大话设计模式》代码样例");System.out.println(); UnitedNationsSecurityCouncil UNSC = new UnitedNationsSecurityCouncil();USA c1 = new USA(UNSC);Iraq c2 = new Iraq(UNSC);UNSC.setUSA(c1);UNSC.setIraq(c2);c1.declare("不准研制核武器,否则要发动战争!");c2.declare("我们没有核武器,也不怕侵略。");System.out.println();System.out.println("**********************************************");}
}abstract class Country {protected UnitedNations unitedNations;public Country(UnitedNations unitedNations){this.unitedNations = unitedNations;}
}class USA extends Country {public USA(UnitedNations unitedNations) {super(unitedNations);}public void declare(String message) {this.unitedNations.declare(message, this);}public void getMessage(String message) {System.out.println("美国获得对方信息:" + message);}
}class Iraq extends Country {public Iraq(UnitedNations unitedNations) {super(unitedNations);}public void declare(String message) {this.unitedNations.declare(message, this);}public void getMessage(String message) {System.out.println("伊拉克获得对方信息:" + message);}
}//中介者类
abstract class UnitedNations{//声明public abstract void declare(String message,Country country);
}//联合国安理会
class UnitedNationsSecurityCouncil extends UnitedNations{private USA countryUSA;private Iraq countryIraq;public void setUSA(USA value) {this.countryUSA = value; }public void setIraq(Iraq value) {this.countryIraq = value; }public void declare(String message, Country country){if (country == this.countryUSA) {this.countryIraq.getMessage(message);}else if (country == this.countryIraq) {this.countryUSA.getMessage(message);}}
}
"我觉得尽管这样的设计可以减少了ConcreteColleague类之间的耦合,但这又使得ConcreteMediator责任太多了,如果它出了问题,则整个系统都会有问题了。"
1.4 中介者的优缺点
"说得好,如果联合国安理会出了问题,当然会对世界都造成影响。所以说,中介者模式很容易在系统中应用,也很容易在系统中误用。当系统出现了'多对多'交互复杂的对象群时,不要急于使用中介者模式,而要先反思你的系统在设计上是不是合理。你来总结一下中介者模式的优缺点吧。"
"我觉得中介者模式的优点首先是Mediator的出现减少了各个Colleague的耦合,使得可以独立地改变和复用各个Colleague类和Mediator,比如任何国家的改变不会影响到其他国家,而只是与安理会发生变化。其次,由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统。比如巴以冲突,本来只能算是国与国之间的矛盾,因此各自的看法可能都比较狭隘,但站在联合国安理会的角度,就可以从全球化、也更客观的角度来看待这个问题,在调停和维和上做出贡献。"
"用中介者模式的确可以从更宏观的角度来看待问题。那中介者模式的缺点呢?"
"就是你刚才提到的,具体中介者类ConcreteMediator会因为ConcreteColleague越来越多,而变得非常复杂,反而不容易维护了。"
"是的,由于ConcreteMediator控制了集中化,于是就把交互复杂性变为中介者的复杂性,这就使得中介者会变得比任何一个ConcreteColleague都复杂。事实上,联合国安理会秘书长的工作应该是非常繁忙的,谁叫他就是'全球最大的官'呢。也正因为此,中介者模式的优点来自集中控制,其缺点也是它,使用时要考虑清楚哦。"
"你平时用.NET写的Windows应用程序中的Form或Web网站程序的aspx就是典型的中介者呀。"
"比如计算器程序,它上面有菜单控件、文本控件、多个按钮控件和一个Form窗体,每个控件之间的通信都是通过谁来完成的?它们之间是否知道对方的存在?"
"哦,我知道了,每个控件的类代码都被封装了,所以它们的实例是不会知道其他控件对象的存在的,比如单击数字按钮要在文本框中显示数字,按照我以前的想法就应该要在Button类中编写给TextBox类实例的Text属性赋值的代码,造成两个类有耦合,这显然是非常不合理的。但实际情况是它们都有事件机制,而事件的执行都是在Form窗体的代码中完成,也就是说,所有的控件交互都是由Form窗体来作中介,操作各个对象,这的确是典型的中介者模式应用。"
"中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合,比如刚才得到的窗体Form对象或Web页面aspx,以及想定制一个分布在多个类中的行为,而又不想生成太多的子类的场合。"
"我相信如果所有的国际安全问题都上升到安理会来解决,世界将不再有战争,世界将会永远和平。让世界充满爱,世界呼唤和平。"
相关文章:

世界需要和平--中介者模式
1.1 世界需要和平 "你想呀,国与国之间的关系,就类似于不同的对象与对象之间的关系,这就要求对象之间需要知道其他所有对象,尽管将一个系统分割成许多对象通常可以增加其可复用性,但是对象间相互连接的激增又会降低…...

PHPStudy(小皮)切换PHP版本PDO拓展失效的问题
因为要看一个老项目,PHP版本在8.0以上会报错,只能切换到7.2,但又遇到了PDO没开启的问题。 PHPStudy上安装的PHP7.2是需要自己配置一下的,里面php.ini文件是空的,需要将php.ini-development改成php.ini,对于…...

Golang 基于共享变量的并发锁
一、互斥锁 先看一个并发情况,同时操作一个全局变量,如果没有锁会怎么样 假设有1000个goroutines并发进行银行余额的扣除,每次都扣除10元,起始的总余额是10000,理论上并发执行完应该是0对不对,但实际却不…...

探索分布式技术--------------注册中心zookeeper
目录 一、ZooKeeper是什么 二、ZooKeeper的工作机制 三、ZooKeeper特点 四、ZooKeeper数据结构 五、ZooKeeper应用场景 5.1统一命名服务 5.2统一配置管理 5.3统一集群管理 5.4服务器动态上下线 5.5软负载均衡 六、ZooKeeper的选举机制 6.1第一次启动选举机制 6.2非…...

剑指offer之牛客与力扣——前者分类题单中的题目在后者的链接
搜索 [4.12完成] JZ1 LCR 172. 统计目标成绩的出现次数 JZ3 153. 寻找旋转排序数组中的最小值 JZ4 LCR 014. 字符串的排列 JZ5 LCR 163. 找到第 k 位数字 400 动态规划 [4.15完成] JZ2 LCR 161. 连续天数的最高销售额 53 JZ3 LCR 127. 跳跃训练 70 JZ4 LCR 126. 斐波那契…...

C# WinForm —— 05 控件简介
简介 窗体中用于输入或操作的对象,有自己的属性、方法、事件 属性:外观方法:功能事件:行为控制特征 可视化,与用户进行交互,属性,方法,事件,可供开发人员使用࿰…...

JavaEE实验三:3.5学生信息查询系统(动态Sql)
题目要求: 使用动态SQL进行条件查询、更新以及复杂查询操作。本实验要求利用本章所学知识完成一个学生信息系统,该系统要求实现3个以下功能: 1、多条件查询: 当用户输入的学生姓名不为空,则根据学生姓名进行学生信息的查询; 当用户…...

【爬虫开发】爬虫从0到1全知识md笔记第5篇:Selenium课程概要,selenium的其它使用方法【附代码文档】
爬虫开发从0到1全知识教程完整教程(附代码资料)主要内容讲述:爬虫课程概要,爬虫基础爬虫概述,,http协议复习。requests模块,requests模块1. requests模块介绍,2. response响应对象,3. requests模块发送请求,4. request…...

【我的代码生成器】React的FrmUser类源码
FrmUser 类的源码中:FrmUser btnSaveClick 等命名方式都是参考VB.Net的写法。 import React, { forwardRef, useImperativeHandle, useState, useEffect, } from "react"; import { makeStyles, TextField, Grid, Paper, Button, ButtonGroup, } from &q…...

Flutter 单例模式的多种实现方法与使用场景分析
单例模式是一种常用的设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。在Flutter应用程序中,单例模式可以有效地管理全局状态、资源共享和对象的生命周期。本文将介绍Flutter中实现单例模式的多种方法,并分析它们的使…...

C语言洛谷题目分享(9)奇怪的电梯
目录 1.前言 2.题目:奇怪的电梯 1.题目描述 2.输入格式 3.输出格式 4.输入输出样例 5.说明 6.题解 3.小结 1.前言 哈喽大家好啊,前一段时间小编去备战蓝桥杯所以博客的更新就暂停了几天,今天继续为大家带来题解分享,希望大…...

vue 中使 date/time/datetime 类型的 input 支持 placeholder 方法
一般在开发时,设置了 date/time/datetime 等类型的 input 属性 placeholder 提示文本时, 发现实际展示中却并不生效,如图: 处理后效果如图: 处理逻辑 判断表单项未设置值时,则设置其伪类样式,文…...

书生·浦语大模型全链路开源体系-第3课
书生浦语大模型全链路开源体系-第3课 书生浦语大模型全链路开源体系-第3课相关资源RAG 概述在 InternLM Studio 上部署茴香豆技术助手环境配置配置基础环境下载基础文件下载安装茴香豆 使用茴香豆搭建 RAG 助手修改配置文件 创建知识库运行茴香豆知识助手 在茴香豆 Web 版中创建…...

Weblogic任意文件上传漏洞(CVE-2018-2894)漏洞复现(基于vulhub)
🍬 博主介绍👨🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收…...

链表基础3——单链表的逆置
链表的定义 #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* next; } Node; Node* createNode(int data) { Node* newNode (Node*)malloc(sizeof(Node)); if (!newNode) { return NULL; } newNode->data …...

Fiddler:网络调试利器
目录 第1章:Fiddler简介和安装 1.1 Fiddler概述 1.2 Fiddler的安装步骤 步骤1:下载Fiddler 步骤2:运行安装程序 步骤3:启动Fiddler 1.3 配置Fiddler代理 配置操作系统代理 配置浏览器代理 Google Chrome Mozilla Firefox 第2章:Fiddler界面和基本操作 2.1 Fi…...

【笔记】mysql版本6以上时区问题
前言 最近在项目中发现数据库某个表的createTime字段的时间比中国时间少了13个小时,只是在数据库中查看显示时间不对,但是在页面,又是正常显示中国时区的时间。 排查 项目中数据库的驱动使用的是8.0.19,驱动类使用的是com.mysq…...

Scala实战:打印九九表
本次实战的目标是使用不同的方法实现打印九九表的功能。我们将通过四种不同的方法来实现这个目标,并在day02子包中创建相应的对象。 方法一:双重循环 我们将使用双重循环来实现九九表的打印。在NineNineTable01对象中,我们使用两个嵌套的fo…...

Excel文件解析
在此模块的学习中,我们需要一个新的开源类库---Apahche POI开源类库。这个类库的用途是:解析并生成Excel文件(Word、ppt)。Apahche POI基于DOM方式进行解析,将文件直接加载到内存,所以速度比较快,适合Excel文件数据量不…...

纯css实现switch开关
代码比较简单,有需要直接在下边粘贴使用吧~ html: <div class"switch-box"><input id"switch" type"checkbox"><label></label></div> css: .switch-box {position: relative;height: 25px…...

Unity3d 微信小游戏 AB资源问题
简介 最近在做微信小游戏,因为对unity比较熟悉,而且微信也支持了用unity3d直接导出到小游戏的工具,所以就记录下这期间遇到的问题 微信小游戏启动时间主要受以下三点影响: 下载小游戏首包数据文件下载和编译wasm代码引擎初始化…...

Leetcode二叉树刷题
给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输入:root [1,2,2,3,4,4,3] 输出:true public boolean isSymmetric(TreeNode root) {if(rootnull)return true;return compare(root.left,root.right);}public boole…...

如何给自己的网站添加 https ssl 证书
文章目录 一、简介二、申请 ssl 证书三、下载 ssl 证书四、配置 nginx五、开放 443 端口六、常见问题解决(一)、配置后,访问 https 无法连接成功(二) 证书配置成功,但是访问 https 还是报不安全 总结参考资料 一、简介 相信大家都知道 https 是更加安全…...

Vue路由跳转及路由传参
跳转 跳转使用 router vue 的路由跳转有 3 个方法: go 、 push 、 replace go :接收数字, 0 刷新,正数前进,负数后退 push :添加,向页面栈中添加一条记录,可以后退 replace &#…...

计算机网络常见面试总结
文章目录 1. 计算机网络基础1.1 网络分层模型1. OSI 七层模型是什么?每一层的作用是什么?2.TCP/IP 四层模型是什么?每一层的作用是什么?3. 为什么网络要分层? 1.2 常见网络协议1. 应用层有哪些常见的协议?2…...

时隔一年,再次讨论下AutoGPT-安装篇
AutoGPT是23年3月份推出的,距今已经1年多的时间了。刚推出时,我们还只能通过命令行使用AutoGPT的能力,但现在,我们不仅可以基于AutoGPT创建自己的Agent,我们还可以通过Web页面与我们创建的Agent进行聊天。这次的AutoGP…...

项目三:学会如何使用python爬虫请求库(小白入门级)
根据上一篇文章我们学会的如何使用请求库和编写请求函数,这一次我们来学习一下爬虫常用的小技巧。 自定义Headers Headers是请求的一部分,包含了关于请求的元信息。我们可以在requests调用中传递一个字典来自定义Headers。代码如下 import requests h…...

【热门话题】PyTorch:深度学习领域的强大工具
🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 💫个人格言: "如无必要,勿增实体" 文章目录 PyTorch:深度学习领域的强大工具一、PyTorch概述二、PyTorch核心特性…...

SQL注入sqli_libs靶场第一题
第一题 联合查询 1)思路: 有回显值 1.判断有无注入点 2.猜解列名数量 3.判断回显点 4.利用注入点进行信息收集 爆用户权限,爆库,爆版本号 爆表,爆列,爆账号密码 2)解题过程࿱…...

QT_day3
完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密码不匹配…...