《Head First 设计模式》笔记21-中介者模式
定义
中介者模式(Mediator Pattern)定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。
场景
解决
模式结构
它主要包含如下几个角色:
- Mediator: 抽象中介者。定义了同事对象到中介者对象之间的接口。
- ConcreteMediator: 具体中介者。实现抽象中介者的方法,它需要知道所有的具体同事类,同时需要从具体的同事类那里接收信息,并且向具体的同事类发送信息。
- Colleague: 抽象同事类。
- ConcreteColleague: 具体同事类。每个具体同事类都只需要知道自己的行为即可,但是他们都需要认识中介者。
在中介者模式中中介者对象处于核心地位,因为它定义了整个系统中所有具体同事类之间的关系。在整个系统中它主要承担两个方面的责任。
结构上起到中转作用。通过中介者对象对关系的封装,使得具体的同事类不再需要显示的引用其他对象,它只需要通过中介者就可以完成与其他同事类之间的通信。
行为上起到协作作用。中介者对同事类之间的关系进行封装,同事类在不需要知道其他对象的情况下通过中介者与其他对象完成通信。在这个过程中同事类是不需要指明中介者该如何做,中介者可以根据自身的逻辑来进行协调,对同事的请求进一步处理,将同事成员之间的关系行为进行分离和封装。
同时由于中介者对对象的关系进行了封装,使得各个同事类之间的耦合减少了,使得他们可以独立改变和复用。
模式实现
这里我们就以租房为例,这里中介机构充当租房者与房屋所有者之间的中介者。
首先是抽象中介者: Mediator.java
public abstract class Mediator {
//申明一个联络方法
public abstract void constact(String message,Person person);
}
然后是抽象同事对象: Person.java
public abstract class Person {
protected String name;
protected Mediator mediator;
Person(String name,Mediator mediator) {
this.name = name;
this.mediator = mediator;
}
}
两个具体同事类:HouseOwner.java
public class HouseOwner extends Person {
HouseOwner(String name, Mediator mediator) {
super(name, mediator);
}
/**
* @desc 与中介者联系
* @param message
* @return void
*/
public void constact(String message) {
mediator.constact(message, this);
}
/**
* @desc 获取信息
* @param message
* @return void
*/
public void getMessage(String message) {
System.out.println("房主:" + name +",获得信息:" + message);
}
}
租房者 Tenant.java
public class Tenant extends Person {
Tenant(String name, Mediator mediator) {
super(name, mediator);
}
/**
* @desc 与中介者联系
* @param message
* @return void
*/
public void constact(String message) {
mediator.constact(message, this);
}
/**
* @desc 获取信息
* @param message
* @return void
*/
public void getMessage(String message){
System.out.println("租房者:" + name +",获得信息:" + message);
}
}
具体中介者对象:中介结构、MediatorStructure.java
public class MediatorStructure extends Mediator {
//首先中介结构必须知道所有房主和租房者的信息
private HouseOwner houseOwner;
private Tenant tenant;
public HouseOwner getHouseOwner() {
return houseOwner;
}
public void setHouseOwner(HouseOwner houseOwner) {
this.houseOwner = houseOwner;
}
public Tenant getTenant() {
return tenant;
}
public void setTenant(Tenant tenant) {
this.tenant = tenant;
}
public void constact(String message, Person person) {
if(person == houseOwner){ //如果是房主,则租房者获得信息
tenant.getMessage(message);
} else{ //反正则是房主获得信息
houseOwner.getMessage(message);
}
}
}
客户端:Client.java
public class Client {
public static void main(String[] args) {
//一个房主、一个租房者、一个中介机构
MediatorStructure mediator = new MediatorStructure();
//房主和租房者只需要知道中介机构即可
HouseOwner houseOwner = new HouseOwner("张三", mediator);
Tenant tenant = new Tenant("李四", mediator);
//中介结构要知道房主和租房者
mediator.setHouseOwner(houseOwner);
mediator.setTenant(tenant);
tenant.constact("听说你那里有三室的房主出租.....");
houseOwner.constact("是的!请问你需要租吗?");
}
}
运行结果:
房主: 张三, 获得信息:听说你那里有三室的房主出租.....
租房者: 李四, 获得信息:是的! 请问你需要租吗?
优缺点
优点
- 简化了对象之间的交互。
- 将各同事解耦。
- 减少子类生成。
- 可以简化各同事类的设计和实现。
缺点
- 在具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
适用环境
在以下情况下可以使用中介者模式:
- 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
- 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象。
- 交互的公共行为,如果需要改变行为则可以增加新的中介者类。
模式应用
MVC架构中控制器
Controller 作为一种中介者,它负责控制视图对象View和模型对象Model之间的交互。如在Struts中,Action就可以作为JSP页面与业务对象之间的中介者。
模式扩展
中介者模式与迪米特法则
- 在中介者模式中,通过创造出一个中介者对象,将系统中有关的对象所引用的其他对象数目减少到最少,使得一个对象与其同事之间的相互作用被这个对象与中介者对象之间的相互作用所取代。因此,中介者模式就是迪米特法则的一个典型应用。
中介者模式与GUI开发
- 中介者模式可以方便地应用于图形界面(GUI)开发中,在比较复杂的界面中可能存在多个界面组件之间的交互关系。
- 对于这些复杂的交互关系,有时候我们可以引入一个中介者类,将这些交互的组件作为具体的同事类,将它们之间的引用和控制关系交由中介者负责,在一定程度上简化系统的交互,这也是中介者模式的常见应用之一。
参考
http://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/mediator.html
https://blog.csdn.net/chenssy/article/details/18443883
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:《Head First 设计模式》笔记21-中介者模式
文章字数:1.6k
本文作者:Bin
发布时间:2018-08-04, 23:17:57
最后更新:2019-08-06, 00:07:35
原始链接:http://coolview.github.io/2018/08/04/Head-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E3%80%8AHead-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%8B%E7%AC%94%E8%AE%B021-%E4%B8%AD%E4%BB%8B%E8%80%85%E6%A8%A1%E5%BC%8F/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。