设计之禅——中介者模式
引言
在面向对象编程中,无可避免的是对象之间的引用,引用给我们带来便捷(对象的复用),但同时也会给类与类之间造成强依赖关系。在一对一的关系中,这看起来并不会造成什么不良的影响,但若是在一对多中,修改任意的一个对象,都会影响到其它调用者,形成强耦合。
中介者
如同上面的图,当对象之间形成网络结构之后,改变5号对象只会影响到4号对象,改变1号对象,其引用它的4、5、6号对象都需要作出相应的改变,而改变2号对象其它5个对象都需要作出改变,我们想要跟踪对象的引用是非常的困难的,因此我们需要将其解耦。 那要如何做呢? 不难发现,我们只需要将网络结构中的一对多的引用改造成为一对一的结构,那么不就非常简单了么。
像上面这样,引入一个中介者对象,所有对象之间的联系都必须通过中介者来处理,这样,所有对象也就只有一个对象与之关联,我们在修改任意的对象时也只需要修改中介者对象对应的逻辑即可,引用的跟踪也不再是难事了。这就是中介者模式的威力。
Coding
在现实生活中,我们可以看到很多中介者的例子,有时我们也会与其打交道,比如找房屋中介租房,下面就以这个例子来说明,首先是房东和租客,这里为了处理方便,使它们都继承自抽象的people类:
public class Person {
protected String name;
protected String message;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return this.name + "收到消息:" + this.message;
}
public void setMessage(String message) {
this.message = message;
}
}
public class Landlord extends Person {
public Landlord(String name) {
super(name);
}
}
public class Tenant extends Person {
public Tenant(String name) {
super(name);
}
}
然后是中介者类(考虑到以后的扩展,抽象出一个抽象的中介者,并持有contact方法,房东和租客则是通过中介者来取得联系)
public abstract class AbstractMediator {
public abstract void contact(String message, Person person);
}
public class HouseMediator extends AbstractMediator {
@Override
public void contact(String message, Person person) {
person.setMessage(message);
}
}
最后测试
public static void main(String[] args) {
AbstractMediator mediator = new HouseMediator();
Person landlord = new Landlord("房东");
mediator.contact("我要租房", landlord);
System.out.println(landlord.getMessage());
Tenant tenant = new Tenant("租客");
mediator.contact("一个月500", tenant);
System.out.println(tenant.getMessage());
}
打印如下结果:
房东收到消息:我要租房
租客收到消息:一个月500
像上面这样就实现了一个中介者模式,我们改动任意的对象(房东或是租客),受到影响的仅仅只有中介者。当然,这里只是为了说明中介者模式,例子本身简单,没有必要使用中介者模式,但不妨想想,对象一旦增多,并相互引用,这个模式带给我们的好处不言而喻。
总结
中介者模式可以帮助我们解除对象之间的耦合,但是在实际编码中并不是经常被使用。因为它会使得体系结构变得非常复杂,在使用该模式之前,我们首先应该想想是不是本身的设计是否存在问题。
- 2017 Multi-University Training Contest - Team 9 1003&&HDU 6163 CSGO【计算几何】
- 【Code】关关的刷题日记21——Leetcode 485. Max Consecutive Ones
- 2017 Multi-University Training Contest - Team 9 1002&&HDU 6162 Ch’s gift【树链部分+线段树】
- 【Java学习笔记之三十二】浅谈Java中throw与throws的用法及异常抛出处理机制剖析
- Linux上访问SQL Server数据库
- 2017 Multi-University Training Contest - Team 9 1001&&HDU 6161 Big binary tree【树形dp+hash】
- 【Java学习笔记之三十三】详解Java中try,catch,finally的用法及分析
- 【Java学习笔记之二十九】Java中的"equals"和"=="的用法及区别
- NET跨平台:在Ubuntu下搭建ASP.NET 5开发环境
- 【Code】关关的刷题日记22——Leetcode 53. Maximum Subarray
- 【Java学习笔记之三十四】超详解Java多线程基础
- Codeforces 842B Gleb And Pizza【几何,水】
- Python3希尔排序
- Codeforces 842A Kirill And The Game【暴力,水】
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【C++简明教程】Python和C++指定元素排序比较
- PG原生解码工具pg_recvlogical的使用-在脑裂时帮我们找回丢失的数据
- 使用XtraBackup备份MySQL 8.0 Part 4 对数据库进行全备
- 介绍一下java的基本类型; 每种数据类型的位数(答错了,太菜了)
- 可读代码编写炸鸡十一 - 小黄鸭从你的心里游到脑子里
- 大数据技术之Hadoop(HDFS)第1章 HDFS概述
- Mongodb多键索引之数组
- 使用XtraBackup备份MySQL 8.0 Part 5 对全备份进行恢复
- LeetCode题目32:最长的有效括号
- C++ 万字长文第二篇---拿下字节面试
- mysqldump命令详解 Part 9 --hex-blob 参数的使用
- 使用XtraBackup备份MySQL 8.0 Part 2 XtraBackup权限及配置
- 使用XtraBackup备份MySQL 8.0 Part 6 对数据库进行增量备份
- ArrayList源码阅读笔记
- 3分钟短文 | Laravel表单验证没规则可用?你试试自定义,真香!