[设计模式] - 中介者模式

一、中介者模式简介

1. 什么是中介者模式

中介者模式(Mediator Pattern) 又叫做调停模式,属于行为型设计模式的一种。其定义为:Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly ,and it lets you vary their interaction independently (用一个中介对象封装一系列的对象交互,中介者使个对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变你它们之间的交互)。简而言之,中介者模式就是一种用来降低多个对象和类之间通讯复杂度的设计模式,这种模式提供了一个中介类来处理类与类之间的通讯行为。

2. 业务说明

我们不用中介来举例似乎都对不起中介者模式这个名字,相信屏幕前有很多小伙伴日常生活中都离不开中介的影子,就比如买房,租房,寻找保姆等等,那么今天我们就简单的通过买房这个生活中的案例来说一说中介者模式是如何使用的。

小明今年准备和恋爱多年的女友结婚,按照中国的传统,准备新房是小两口首先要准备的事情。虽然有专门负责提供买房服务的中介,但是由于小明觉得3个点的中介费过于高昂,于是决定自己来完成整个买房流程,于是通过查询资料小明初步的了解一下买房的步骤。

在这里插入图片描述
当然为了减少文章的篇幅,我们还需要简化一下这个模型:
在这里插入图片描述
那么接下来我们看一下如果不使用中介者模式,该如何实现这个逻辑呢?

3. 不使用中介者模式的代码实现

购房者:小明

// 租房者 小明
public class Customer {
	// 个人信息是否存在违规
	private Boolean information;
	private Seller seller ;

	public void buyHouse(String msg) {
		System.out.println("购房者:准备买一个需求为:" + msg + "的房屋");
		// 创建一个房东
		// 房东的房子是否匹配需求
		seller.match(msg);
		// 房东是否出售
		seller.ifSell();
		// 房东决定出售 ,前往房管局查询信息
		Manager manager = new Manager();
		Boolean check = manager.check(this, seller);
		if (check) {
			System.out.println("交易成功");
		} else {
			System.out.println("交易失败");
		}
	}

	public Seller getSeller() {
		return seller;
	}

	public void setSeller(Seller seller) {
		this.seller = seller;
	}

	public Customer(Boolean information) {
		super();
		this.information = information;
	}

	public Boolean information() {
		return information;

	}

	public void getMsg() {
		System.out.println("购房者:" + "接到房管局通知购房者有违约记录");

	}

}

出售者:房东

// 出售人 房东
public class Seller {
	// 是否出售
	private Boolean ifSell = true;
	// 个人信息是否违规
	private Boolean information;

	public void match(String msg) {
		// TODO Auto-generated method stub

	}

	public Boolean ifSell() {
		return ifSell;

	}

	public Boolean information() {
		return information;
	}

	public void getMsg() {
		System.out.println("房管局通知购房者有违约记录");
	}

	public Seller(Boolean ifSell, Boolean information) {
		super();
		this.ifSell = ifSell;
		this.information = information;
	}

}

管理者:房管局

public class Manager {

	public Boolean check(Customer customer, Seller seller) {
		// 获取房东和购买者的个人信息
		Boolean information = customer.information();
		seller.information();
		if (!customer.information()) {
			seller.getMsg();
			System.out.println("房管局:" + "购房者个人审核未通过");
			return false;
		}
		if (!seller.information()) {
			customer.getMsg();
			System.out.println("房管局:" + "房东个人审核未通过");
			return false;
		}
		System.out.println("房管局:" + "审核通过,可以交易");
		return true;
	}

}

测试代码

public class Client {
	public static void main(String[] args) {
		Customer customer = new Customer(true);
		// 创建出售人
		Seller seller = new Seller(true, true);
		customer.setSeller(seller);
		customer.buyHouse("价格便宜,又大又好的房子");
	}
}

测试结果
在这里插入图片描述
到这里一个简单的购房流程就已经实现了,这里我们来看下这么做有没有什么问题呢?

  1. 首先每个类都与其他的两个类产生了关联关系,而迪米特法则认为每个类应该只和有直接关系的类关联,如果关联的类多了,则会造成类的膨胀和增加类与类之间的耦合度,想要修改其中一个就要修改所有的关联类。
  2. 如果我们想要修改购房的流程,就需要直接对customer类进行修改,这无疑也是违反了开闭原则的。

那么我们该如何解决这个问题呢?这个时候中介者模式就要登场了。

二、中介者模式的实现

1. 设计思路

我们先来优化一下上面的设计思路:

  1. 首先我们不希望购房者,房东和房管局之间产生关联
  2. 第二点我们不希望购房者过多的参与业务

那么这个时候我们就需要提供一个为他们办事的人:中介。其实中介者模式和中介的作用很像,他们的都是将一个环形的关系图转换为一个星型的关系图,如果你不理解的话请看接下来的这个图:

在这里插入图片描述
如图我们看到原本三者互相依赖的关系转变为了三者都只与中介进行交互,中介负责替三者传递消息。详细来说就是中介将购房者,房东,房管局三者都看作为了客户,客户首先需要找到中介进行委托(中介者需要提供注册功能),然后向中介传递需求(发送消息),中介根据客户的消息来进行业务处理和转发客户的信息给其他需要的客户,其他客户接收消息进行接下来的业务操作。于是我们可以简单的概括下中介者模式需要用到的角色:

  1. 中介者(Mediator): 负责制定统一的业务接口,用于各个客户之间的通讯。
  2. 客户(Colleague):有的教程也喜欢叫做同事,其主要拥有两种行为:一种是客户本身的行为,比如改变自身的某些状态,这种行为叫做自发行为(Self-Method),与其他客户类或中介者没有关系;另外一种方法是必须依赖中介者才能完成的行为,叫做依赖方法(Dep-Method)。

接着我们将购房这个流程加入中介后,设计一个简单的类图:
在这里插入图片描述
好了,接下来我们来做代码实现。

2. 代码实现

创建抽象中介和中介实例

// 抽象中介
public abstract class Mediator {

	protected Map<String, Colleague> registerMap = new HashMap<>();

	// 注册客户
	public void register(String name, Colleague colleague) {
		registerMap.put(name, colleague);
	}

	// 删除用户
	public void remove(String name) {
		registerMap.remove(name);
	}

	// 执行方法
	abstract void execute(String msg);

}
// 中介实例
public class HouseMediator extends Mediator {

	@Override
	void execute(String role) {
		Colleague colleague = registerMap.get(role);
		if (role.equals("Customer")) {
			// 如果是房客申请 则需要查找已注册的房东 查看是否匹配
			Seller seller = (Seller) registerMap.get("Seller");
			seller.getMsg("有一个房客需要"+colleague.sendMsg());
		} else if (role.equals("Seller")) {
			Customer customer = (Customer) registerMap.get("Customer");
			customer.getMsg(colleague.sendMsg());
		} else if (role.equals("Manager")) {
			Seller seller = (Seller) registerMap.get("Seller");
			Customer customer = (Customer) registerMap.get("Customer");
			seller.getMsg(colleague.sendMsg());
			customer.getMsg(colleague.sendMsg());
		}
	}

}

创建客户(同事)接口与实例

// 客户接口
public interface Colleague {
	// 发送消息
	String sendMsg();
	// 接受消息
	void getMsg(String str);
}
// 购房者
public class Customer implements Colleague {

	private Mediator houseMediator;

	private String role;

	private String msg;

	public Customer(Mediator houseMediator, String role) {
		super();
		this.houseMediator = houseMediator;
		this.role = role;
		houseMediator.register(role, this);
	}

	// 自发行为
	public void buyHouse(String msg) {
		this.msg = msg;
		System.out.println("购房者:准备买一个需求为:" + msg + "的房屋");
		houseMediator.execute(role);
	}

	@Override
	public String sendMsg() {
		return msg;
	}

	@Override
	public void getMsg(String msg) {
		System.out.println("购房者接收到消息:" + msg);
	}

}
//房东
public class Seller implements Colleague {

	private Mediator houseMediator;

	private String role;

	private String msg;

	public Seller(Mediator houseMediator, String role) {
		super();
		this.houseMediator = houseMediator;
		this.role = role;
		houseMediator.register(role, this);
	}

	public void sell() {
		// 房东决定卖方
		System.out.println("房东同意出售房屋");
		this.msg= "房东同意出售房屋" ;
		houseMediator.execute(role);
	}

	@Override
	public String sendMsg() {
		return msg;
	}

	@Override
	public void getMsg(String msg) {
		System.out.println("房东:" + "接收到了一条信息:" + msg);
	}
}
//房管局
public class Manager implements Colleague {

	private Mediator houseMediator;

	private String role;

	private String msg;

	public Manager(Mediator houseMediator, String role) {
		super();
		this.houseMediator = houseMediator;
		this.role = role;
		houseMediator.register(role, this);
	}

	public void check() {
		this.msg = "房管局核实无误,可以交易";
		houseMediator.execute(role);
	}

	@Override
	public String sendMsg() {
		// TODO Auto-generated method stub
		return msg;
	}

	@Override
	public void getMsg(String msg) {
		System.out.println("房管局接收到消息" + msg);
	}

}

测试代码

public class Client {
	public static void main(String[] args) {
		Mediator houseMediator = new HouseMediator();
		Customer customer = new Customer(houseMediator,"Customer");
		Seller seller = new Seller(houseMediator, "Seller");	
		Manager manager = new Manager(houseMediator, "Manager");
		customer.buyHouse("又便宜又大的房子");
		seller.sell();
		manager.check();
	}
}

测试结果:
在这里插入图片描述
好了,到这里一个中介者模式的实现我们就写完了。

三、中介者模式总结

1. 中介者模式的特点

优点: 减少了类与类之间的依赖,把原有的一对多模型转换为了一对一的依赖,客户只依赖于中介者,降低了类间的耦合。
缺点: 中介者类会膨胀的很大而且逻辑复杂,客户类越多,中介者类就越复杂且难以维护。

2. 中介者模式的使用场景

中介者模式首先实现并不简单,且容易误用。在面向对象编程中,对象和对象之间必然存在依赖关系,我们要分清楚具体的业务场景来判断中介者模式是否适用,判断的标准就是多个对象之间是否存在紧密耦合的关系,即在类图中是否出现了蜘蛛网状的关系图。这里给大家简单的说几个实际中经常用到的案例:

  1. 机场调度
  2. 开发中用到的MVC模式
  3. 媒体网关
  4. 中介服务
  5. 组织结构,如联合国,世贸组织等

四、结语

今天的代理模式讲解就全部结束了,设计模式的相关代码已经在gitee上收录,有需求的小伙伴可以直接拿走:

https://gitee.com/xiaolong-oba/csdn-learning-code.git

有疑问的小伙伴欢迎评论区留言或者私信博主,博主会在第一时间为你解答。

这里插播一个CSDN官方举办的活动来恰个饭:
如果有想要学习Java但基本功薄弱的同学,可以点击链接查看CSDN程序员学院提供的教学课程来进行自我提升,实现在新的一年里升职加薪~

Java语言零基础入门实战
一站式掌握Java语法,轻松度过Java开发第一关,快来学习吧~
在这里插入图片描述

Java面试核心考点突击大串讲
从经典Java面试题出发,剖析面试题,整理Java面试必考知识点,给出面试的常见回答以及加分回答,让你领略题目背后考察的能力,梳理Java知识体系。
在这里插入图片描述

码字不易,感到有收获的小伙伴记得要关注博主一键三连,不要当白嫖怪哦~
博主在这里祝大家可以在新的一年升职加薪,走上人生巅峰!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓龙oba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值