Windows环境下实现设计模式——中介者模式(JAVA版)

news2024/11/13 9:40:33

我是荔园微风,作为一名在IT界整整25年的老兵,今天总结一下Windows环境下如何编程实现中介者模式(设计模式)。

不知道大家有没有这样的感觉,看了一大堆编程和设计模式的书,却还是很难理解设计模式,无从下手。为什么?因为你看的都是理论书籍。

我今天就在Windows操作系统上安装好JAVA的IDE编程工具,并用JAVA语言来实现一个中介者模式,真实的实现一个,你看懂代码后,自然就明白了。

中介者模式Mediator Pattern  (行为型设计模式)

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

上面定义听懂了吗?莫名其妙看不懂对吧。所以我们还是来看看实现生活中的例子。
 

某软件公司推出一款知识社区问答软件,已经成为很多人学习、工作和生活的一部分。在社区的用户沟通中,一般有两种方式:第一种是用户与用户直接私信沟通,第二种是通过社区群进行沟通,一个用户如果要与别的用户沟通或发送文件,通常需要加其他用户为好友,用户与用户之间存在多对多的联系,这将导致系统中用户之间的关系非常复杂,一个用户如果要将相同的问答信息或文件发送给其他所有用户,必须一个一个的发送,于是社区群产生了,如果使用社区群,一个用户就可以向群内的多个用户发送相同的信息和文件而无须一个一个发送,只需要将信息或文件发送到群中或作为群共享即可,群的作用就是将发送者所发送的信息和文件转发给每一个接收者用户。通过引入社区群的机制,将极大减少系统中用户之间的两两通信,用户与用户之间的联系可以通过社区群来实现。

在这些软件中,某些类/对象之间的相互调用关系错综复杂,类似社区用户之间的关系,此时,我们特别需要一个类似社区群一样的中间类来协调这些类/对象之间的复杂关系,以降低系统的耦合度。如何解决这个问题,那就是本文将要介绍的中介者模式

如果在一个系统中对象之间的联系呈现为网状结构,对象之间存在大量的多对多联系,将导致系统非常复杂,这些对象既会影响别的对象,也会被别的对象所影响,它们之间通过彼此的相互作用实现系统的行为。在网状结构中,几乎每个对象都需要与其他对象发生相互作用,而这种相互作用表现为一个对象与另外一个对象的直接耦合,这将导致一个过度耦合的系统。

 中介者模式可以使对象之间的关系数量急剧减少,通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构,在这个星形结构中,对象不再直接与另一个对象联系,它通过中介者对象与另一个对象发生相互作用。中介者对象的存在保证了对象结构上的稳定,也就是说,系统的结构不会因为新对象的引入带来大量的修改工作。

如果在一个系统中对象之间存在多对多的相互关系,我们可以将对象之间的一些交互行为从各个对象中分离出来,并集中封装在一个中介者对象中,并由该中介者进行统一协调,这样对象之间多对多的复杂关系就转化为相对简单的一对多关系。

在中介者模式中,我们引入了用于协调其他对象/类之间相互调用的中介者类,为了让系统具有更好的灵活性和可扩展性,通常还提供了抽象中介者,其结构图如图所示:

在中介者模式结构图中包含如下几个角色:Mediator(抽象中介者):它定义一个接口,该接口用于与各对象之间进行通信。ConcreteMediator(具体中介者):它是抽象中介者的子类,通过协调各个对象来实现协作行为,它维持了对各个对象的引用。Colleague(抽象类):它定义各个类公有的方法,并声明了一些抽象方法来供子类实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。ConcreteColleague(具体类):它是抽象类的子类;每一个对象在需要和其他对象通信时,先与中介者通信,通过中介者来间接完成与其他类的通信;在具体类中实现了在抽象类中声明的抽象方法。

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

 (1) 中转作用(结构性):通过中介者提供的中转作用,各个对象就不再需要显式引用其他同事,当需要和其他对象进行通信时,可通过中介者来实现间接调用。该中转作用属于中介者在结构上的支持。

 (2) 协调作用(行为性):中介者可以更进一步的对对象之间的关系进行封装,对象可以一致的和中介者进行交互,而不需要指明中介者需要具体怎么做,中介者根据封装在自身内部的协调逻辑,对对象的请求进行进一步处理,将对象成员之间的关系行为进行分离和封装。该协调作用属于中介者在行为上的支持。

 在中介者模式中,典型的抽象中介者类代码如下所示:

public abstract class Mediator {
	protected ArrayList<Colleague> colleagues=new ArrayList<Colleague>(); //存储对象
 
    //注册方法,用于增加对象
	public void register(Colleague colleague) {
		colleagues.add(colleague);
	}
 
	//声明抽象的业务方法
	public abstract void operation();
}

在抽象中介者中可以定义一个类的集合,用于存储对象并提供注册方法,同时声明了具体中介者类所具有的方法。在具体中介者类中将实现这些抽象方法,具体中介者类代码如下所示:

public class ConcreteMediator extends Mediator {
    //实现业务方法,封装调用
	public void operation() {
		......
		((Colleague)(colleagues.get(0))).method1(); //通过中介者调用类的方法
		......
	}
}

在具体中介者类中将调用类的方法,调用时可以增加一些自己的业务代码对调用进行控制。在抽象类中维持了一个抽象中介者的引用,用于调用中介者的方法,典型的抽象类代码如下所示:

public abstract class Colleague {
	protected Mediator mediator; //维持一个抽象中介者的引用
	
	public Colleague(Mediator mediator) {
		this.mediator=mediator;
	}
	
	public abstract void method1(); //声明自身方法,处理自己的行为
	
	//定义依赖方法,与中介者进行通信
	public void method2() {
		mediator.operation();
	}
}

在抽象类中声明了类的抽象方法,而在具体类中将实现这些方法,典型的具体类代码如下所示:

public class ConcreteColleague extends Colleague {
	public ConcreteColleague(Mediator mediator) {
		super(mediator);
	}
	
    //实现自身方法
	public void method1() {
		......
	}
}

在具体类ConcreteColleague中实现了在抽象类中声明的方法,其中方法method1()是类的自身方法(Self-Method),用于处理自己的行为,而方法method2()是依赖方法(Depend-Method),用于调用在中介者中定义的方法,依赖中介者来完成相应的行为,例如调用另一个类的相关方法。
 

应用实例

下面来看一个具体例子,市公共资源交易中心的大厅里放着一个机器人,可以让工作人员进行操作的机器,上面的软件可以控制今天进厂交易的企业和排序,一旦工作人员打入交易内容,便会在大厅的电子大屏上显示出来。对于系统中存放在交易企业名称,可以通过机器人的控制面板上的各种按钮灵活的进行增删改查。

 Component充当抽象类,机器人控制面板上的Button、List、ComboBox和TextBox充当具体类,Mediator充当抽象中介者类,ConcreteMediator充当具体中介者类,ConcreteMediator维持了对具体类的引用,为了简化ConcreteMediator类的代码,我们在其中只定义了一个Button对象和一个TextBox对象。
 

(1)Mediator(抽象中介者):

package designpatterns.mediator;

public abstract class Mediator {
	public abstract void componentChanged(Component c);
}

(2)ConcreteMediator(具体中介者):

package designpatterns.mediator;

public class ConcreteMediator extends Mediator {
	//维持对各个对象的引用
	public Button addButton;
	public List list;
	public TextBox userNameTextBox;
	public ComboBox cb;
 
    //封装对象之间的交互
	public void componentChanged(Component c) {
		//单击按钮
        if(c == addButton) {
			System.out.println("--单击增加按钮--");
			list.update();
			cb.update();
			userNameTextBox.update();
		}
        //从列表框选择
		else if(c == list) {
			System.out.println("--从列表框选择企业--");
			cb.select();
			userNameTextBox.setText();
		}
        //从组合框选择
		else if(c == cb) {
			System.out.println("--从组合框选择企业--");
			cb.select();
			userNameTextBox.setText();
		}
	}
}

(3)Colleague(抽象类):

package designpatterns.mediator;

public abstract class Component {
	protected Mediator mediator;
	
	public void setMediator(Mediator mediator) {
		this.mediator = mediator;
	}
 
	//转发调用
	public void changed() {
		mediator.componentChanged(this);
	}
	
	public abstract void update();	
}

(4)ConcreteColleague(具体类):

package designpatterns.mediator;

//按钮类:具体类
public class Button extends Component {
	public void update() {
		//按钮不产生交互
	}
}
 
//列表框类:具体类
public class List extends Component {
	public void update() {
		System.out.println("列表框增加一项:A企业。");
	}
	
	public void select() {
		System.out.println("列表框选中项:B企业。");
	}
}
 
//组合框类:具体类
public class ComboBox extends Component {
	public void update() {
		System.out.println("组合框增加一项:A企业。");
	}
	
	public void select() {
		System.out.println("组合框选中项:B企业。");
	}
}
 
//文本框类:具体类
public class TextBox extends Component {
	public void update() {
		System.out.println("文本框清空。");
	}
	
	public void setText() {
		System.out.println("文本框显示:A企业。");
	}
}

(5)Client(客户端):

package designpatterns.mediator;

public class Client {
	public static void main(String args[]) {
        //定义中介者对象
		ConcreteMediator mediator;
		mediator = new ConcreteMediator();
		
        //定义对象
		Button adde = new Button();
		List list = new List();
	    ComboBox cb = new ComboBox();
	    TextBox tb = new TextBox();
 
		adde.setMediator(mediator);
		list.setMediator(mediator);
		cb.setMediator(mediator);
		tb.setMediator(mediator);
 
		mediator.addButton = adde;
		mediator.list = list;
		mediator.cb = cb;
		mediator.userNameTextBox = tb;
		
		adde.changed();
		list.changed();
	}
}

中介者模式将一个网状的系统结构变成一个以中介者对象为中心的星形结构,在这个星型结构中,使用中介者对象与其他对象的一对多关系来取代原有对象之间的多对多关系。中介者模式在事件驱动类软件中应用较为广泛,特别是基于GUI(Graphical User Interface,图形用户界面)的应用软件,此外,在类与类之间存在错综复杂的关联关系的系统中,中介者模式都能得到较好的应用。

各位小伙伴,这次我们就说到这里,下次我们再深入研究windows环境下的各类设计模式实现。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/448979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

modbus指令测试

目录 一.抓包二.modbus与plc三.usb包分析四.编写modbus指令测试五.调试工具 一.抓包 1.串口抓包&#xff1f;wireshark&#xff01;: https://xuxeu.github.io/uart-catch/ 2.Windows&Linux USB抓包方法总结:https://zhuanlan.zhihu.com/p/267820933 3.USB The Setup Pack…

(“树” 之 前中后序遍历 ) 94. 二叉树的中序遍历 ——【Leetcode每日一题】

基础概念&#xff1a;前中后序遍历 1/ \2 3/ \ \ 4 5 6层次遍历顺序&#xff1a;[1 2 3 4 5 6]前序遍历顺序&#xff1a;[1 2 4 5 3 6]中序遍历顺序&#xff1a;[4 2 5 1 3 6]后序遍历顺序&#xff1a;[4 5 2 6 3 1] 层次遍历使用 BFS 实现&#xff0c;利用的就是 BFS…

一文搞懂Java中的异常问题

思考几个问题 1&#xff1a;JavaWeb系统中&#xff0c;我的代码未做任何处理&#xff0c;报错了还会往下执行吗&#xff1f; 2&#xff1a;JavaWeb系统中&#xff0c;我的代码做了 try catch finally, 报错了还会往下执行吗&#xff1f; 3&#xff1a;JavaWeb系统中&#xff0c…

软考高频考点--《项目采购管理》

现在离2023年上半年软考还有一个多月的时间&#xff0c;相信各位小伙伴们已经进入紧张的备考状态了。 小编今天为大家整理了软考的一些高频考点–《项目采购管理》&#xff0c;希望对正在备考软考的你有所帮助&#xff01; 采购是从项目团队外部获得产品、服务或成果的完整的购…

alsa_lib移植到IMX6ULL

简介 ALSA是Advanced Linux Sound Architecture的缩写&#xff0c;目前已经成为了linux下的主流音频体系架构&#xff0c;提供了音频和MIDI的支持。 交叉编译alsa_lib和alsa_utils 下载alsa_lib 在官网中下载AlsaProject 编译 先将文件解压&#xff0c;然后进入alsa_lib…

运筹说 第94期|论文速读之基于关键路径的置换流水车间调度问题

前几期的推送已经讲解了网络计划的基本知识、数学模型和相关算法&#xff0c;相信大家对网络计划已经有了充分的了解&#xff0c;这期小编将带大家一起来读一篇基于关键路径的置换流水车间调度问题的文章。 1.文章信息 题目&#xff1a;An efficient critical path based meth…

手把手教你分析解决MySQL死锁问题

在生产环境中出现MySQL死锁问题该如何排查和解决呢&#xff0c;本文将模拟真实死锁场景进行排查&#xff0c;最后总结下实际开发中如何尽量避免死锁发生。 一、准备好相关数据和环境 当前自己的数据版本是8.0.22 mysql> select version; ----------- | version | --------…

Arduino 多任务软件定时器:Simpletimer库的使用

Arduino 多任务软件定时器:Simpletimer库的使用 📌Simpletimer库Arduino官方介绍信息:https://playground.arduino.cc/Code/SimpleTimer/✨该库也是利用了millis()函数来实现任务轮询的。与之类似的还有ESP8266固件自带的Ticker库,但是Ticker库使用仅限于ESP8266内调用,Si…

Discourse Google Analytics 3 的升级提示

根据 Google 官方的消息&#xff1a; Google Analytics&#xff08;分析&#xff09;4 是我们的新一代效果衡量解决方案&#xff0c;即将取代 Universal Analytics。自 2023 年 7 月 1 日起&#xff0c;标准 Universal Analytics 媒体资源将停止处理新的命中数据。如果您仍在使…

linux-01-基础回顾

文章目录 Linux-Day01课程内容1. 前言1.1 什么是Linux1.2 为什么要学Linux1.3 学完Linux能干什么 2. Linux简介2.1 主流操作系统2.2 Linux发展历史2.3 Linux系统版本 3. Linux安装3.1 安装方式介绍3.2 安装VMware3.3 安装Linux TODO3.4 网卡设置3.5 安装SSH连接工具3.5.1 SSH连…

【Python】【进阶篇】1、Django是什么?

目录 1、Django是什么&#xff1f;1. Django的由来2. Django的命名3. Django的版本发布1) 功能版2) 补丁版3) LTS 版本 4. Django框架的特点 1、Django是什么&#xff1f; Django 是使用 Python 语言开发的一款免费而且开源的 Web 应用框架。由于 Python 语言的跨平台性&#…

IDA调试

IDA动态调试 有时候程序在运行过程中会生成一些关键的数值&#xff0c;而人力通过静态分析的结果模拟程序的运行来推出这些中间的数值可能很麻烦。简单重复的工作是计算机所擅长的而不是人&#xff0c;所以我们可以让这个程序运行起来&#xff0c;得到这些中间过程的数值。这就…

VLAN与access接口、hybrid接口实验

[r1]dhcp enable //开启DHC0功能P [r1-GigabitEthernet0/0/0]int g 0/0/0.1 [r1-GigabitEthernet0/0/0.1]ip add 192.168.1.1 24 [r1-GigabitEthernet0/0/0.1]dhcp select interface //接口地址池 [r1-GigabitEthernet0/0/0.1]dhcp server dns-list 8.8.8.8 [r1-GigabitEthern…

【Linux】输入系统详述 + 触摸屏应用实战(tslib)

目录简述 前言&#xff1a; 一、输入系统 二、Linux输入系统框架 &#xff08;1&#xff09;输入系统的驱动层 &#xff08;2&#xff09;输入系统核心层 &#xff08;3&#xff09;输入系统事件层 三、APP访问硬件的方式 &#xff08;1&#xff09;查询方式、休眠-唤醒…

Linux环境下安装RocketMQ

目录 前置要求&#xff1a; 一、下载RocketMQ 二、上传解压 三、配置rocketmq的环境变量 四、查看rocketmq的目录结构 五、启动 5.1 启动nameserver 5.2 启动broker 六、测试发送消息 七、关闭 前置要求&#xff1a; 准备一台Linux系统的虚拟机提前安装jdk1.8 不会…

C++函数重载的简单介绍

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【C之路】 中华文化博大精深&#xff0c;我们知道在我们的汉语中&#xff0c;每个词语都有着其不同的含义&#xff0c;甚至是一个词语中有…

毫米波雷达将被颠覆?楚航科技发布隐形雷达ART

4月19日上海车展现场&#xff0c;楚航科技首次对外展示最新的前瞻性研发第N代创新产品——隐形雷达ART。 楚航科技本次发布的科技隐形雷达ART&#xff0c;打破一体式封装设计&#xff0c;重新定义车载毫米波雷达物理形态&#xff0c;为行业提供全新的颠覆性产品设计新路线。 资…

LeetCode 1000. Minimum Cost to Merge Stones【记忆化搜索,动态规划,数组】困难

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

【C++类和对象】类和对象(中):析构函数 {析构函数的概念及特性,编译器自动生成的析构函数,构造析构的顺序}

三、析构函数 3.1 概念 通过前面构造函数的学习&#xff0c;我们知道一个对象是怎么来的&#xff0c;那一个对象又是怎么没呢的&#xff1f; 析构函数&#xff1a;与构造函数功能相反&#xff0c;析构函数不是完成对对象本身的销毁&#xff0c;局部对象随函数栈帧的销毁而销毁…

chatGpt自动写文章-chatGpt自动写文章软件

怎么用GPT写文章 使用GPT写文章需要按照以下步骤进行&#xff1a; 确定文章主题&#xff1a;首先需要明确文章的主题&#xff0c;这有助于GPT更好地了解你想要表达的内容&#xff0c;并生成更有针对性的文本。 准备开头和结尾&#xff1a;根据文章主题&#xff0c;准备好文章开…