设计模式-中介者模式

一、中介者模式的核心思想

中介者模式的核心思想:用一个中介对象来封装一系列关于对象交互行为。各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉及到修改很多其他对象的行为,如果使用 Mediator 模式,可以使各个对象间的耦合松散,只需关心和 Mediator的关系,使多对多的关系变成了一对多的关系,可以降低系统的复杂性,提高可修改扩展性。

中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。简单点来说,将原来两个直接引用或者依赖的对象拆开,在中间加入一个“中介”对象,使得两头的对象分别和“中介”对象引用或者依赖。

中介者模式的组成包括如下。

  • 中介者接口 Mediator:抽象中介者定义统一的接口用于各目标用户对象之间的通信。
  • 中介者实现类 MyMediator:具体中介者通过协调各用户实现协作行为,为此它要知道并引用各个用户对象。
  • 抽象用户类 User:为用户的行为定义统一的操作接口。
  • 具体用户类 MyUser1 和 MyUser2:每一个用户都知道对应的具体中介者,而且与其他的用户通信的时候,一定要通过中介者协作。

中介者模式的结构图如下图所示
在这里插入图片描述
下面来看具体的实现。

(1) 中介者接口 Mediator.java 定义了尽可能多的访问用户的接口,例如 workAll()表示调用所有的用户操作函数。

package behavior.mediator;

/**
* @author Minggg
* 中介者接口
*/
public interface Mediator {

	public void createMediator();
	public void workAll();
}

(2) 中介者实现类 MyMediator.java负责管理多个用户对象,并负责真正实现交互操作的内容。

package behavior.mediator;

/**
* @author Minggg
* 中介者实现类
*/
public class MyMediator implements Mediator {

	private User user1;
	private User user2;
	
	public User getUser1() {
		return user1;	
	}
	
	public User getUser2() {
		return user2;	
	}
	
	public void createMediator(){
		user1 = new MyUser1(this);
		user2 = new MyUser2(this);
	}
	
	public void workAll() {
		user1.work();
		user2.work();
	}
}

(3) 用户接口 User.java 只能够与中介者 Mediator 交互,不能够与其他用户对象交互,因此它拥有一个 Mediator对象。

package behavior.mediator;

/**
* @author Minggg
* 用户接口
*/
public abstract class User {

	private Mediator mediator;
	
	public Mediator getMediator() {
		return mediator;	
	}
	
	public User(Mediator mediator) {
		this.mediator = mediator;
	}
	
	public abstract void work();
	
}

(4) 用户实现类 MyUser1.java是一个 User 接口的具体实现。

package behavior.mediator;

/**
* @author Minggg
* 用户实现类
*/
public class MyUser1 extends User {

	public MyUser1(Mediator mediator){
		super(mediator);	
	}
	
	public User(Mediator mediator) {
		this.mediator = mediator;
	}
	
	public void work(){
		System.out.println("User1 执行");
	}
	
}

(5) 用户实现类MyUser2.java是一个 User 接口的具体实现。

package behavior.mediator;

/**
* @author Minggg
* 用户实现类
*/
public class MyUser2 extends User {

	public MyUser2(Mediator mediator){
		super(mediator);	
	}
	
	public User(Mediator mediator) {
		this.mediator = mediator;
	}
	
	public void work(){
		System.out.println("User2 执行");
	}
	
}

对 User 的不同对象进行操作,只需要通过中介者来进行统一管理,而不需要直接访问用户对象。创建一个 Mediator 对象,只需要执行 workAll()函数即可实现对所有用户的操作。

package behavior.mediator;

/**
* @author Minggg
* 测试类 
*/
public class Test {

	public static void main(String[] args) {
		Mediator mediator = new MyMediator();
		mediator.createMediator():
		mediator.workAll();
	}
	
}

运行该程序的结果如下:

User1 执行
User2 执行

以上程序只是演示了中介者与用户之间的解耦关系,在实际的开发中,则可以灵活运用,丰富它们的功能。

二、何时使用中介者模式

由于中介者模式在定义上比较松散,在结构上与观察者模式、命令模式十分相像,而应用目的又与外观模式有些相似。

  • 在结构上,中介者模式与观察者模式、命令模式都添加了中间对象–只是中介者去掉了后两者在行为上的方向。因此中介者的应用可以仿照后两者的例子去写。但是观察者模式命令模式中的观察者、命令都是被客户所知的,具体哪个观察者、命令的应用都是由客户来指定的:而大多中介者角色对于客户程序却是透明的。当然造成这种区别的原因是由于它们要达到的目的不同。
  • 从目的上看,中介者模式与观察者模式、命令模式便没有了任何关系,倒是与前面讲过的外观模式有些相似。但是外观模式是介于客户程序与子系统之间的,而中介者模式是介于子系统与子系统之间的。这也注定了它们有很大的区别:外观模式是将原有的复杂逻辑提取到一个统一的接口,简化客户对逻辑的使用。它是被客户所感知的,而原有的复杂逻辑则被隐藏了起来。而中介者模式的加入并没有改变客户原有的使用习惯,它是隐藏在原有逻辑后面的,使得代码逻辑更加清晰可用。

使用中介者模式最大的好处就是将用户角色解耦。这带来了一系列的系统结构改善:提高了原有系统的可读性、简化原有系统的通信协议–将原有的多对多变为一对多,提高了代码的可复用性。但是中介者集中了太多的责任,所有有关的用户对象都要由它来控制。在使用中介者模式的时候注意控制中介者角色的大小。

中介者模式的使用时机:一组对象以定义良好但是复杂的方式进行通信,产生了混乱的依赖关系,且导致对象难以复用。

三、Java中的应用–Java 多线程数据共享

在Java多线程的生产者与消费者实例中,生产者生产商品,消费者消费商品,如果这两者之间进行相互通信将会造成沟通上的麻烦。比如,有10个生产者和100个消费者,如果10个生产者都与100个消费者进行通信,那对于程序编码者来说将是一种灾难。

以上情况可以采用中介者模式,将所有的生产者和所有的消费者都与一个中介对象ProductList关联起来,他们只需要与这一个中介对象通信即可。ProductList是一个生产者与消费者共享的中介对象,它决定了什么情况下生产者要 wait(),什么情况下消费者要 wait()。可以把 ProductList看做一个产品仓库,当产品仓库满的时候,生产者线程需要wait(),从而放弃对产品仓库的控制。这个时候消费者线程就可以进来而取得仓库的控制权。一旦消费者消费了产品,那么仓库就不满了。这个时候消费者线程就要 notifyAll()生产者线程,让等待的生产者线程唤醒。但是生产者被唤醒后不能马上进行生产,因为它在 wait()的时候已经丧失了对仓库的控制权,所以就需要等待消费者线程结束操作,才能重新取得仓库的控制权,再进行生产。

相关推荐

  1. 设计模式——中介模式

    2024-07-10 22:14:02       58 阅读
  2. 设计模式-中介模式

    2024-07-10 22:14:02       59 阅读
  3. 设计模式中介模式

    2024-07-10 22:14:02       39 阅读
  4. 设计模式中介模式

    2024-07-10 22:14:02       35 阅读
  5. 设计模式-中介模式

    2024-07-10 22:14:02       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 22:14:02       114 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 22:14:02       124 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 22:14:02       101 阅读
  4. Python语言-面向对象

    2024-07-10 22:14:02       112 阅读

热门阅读

  1. k8s离线安装单节点elasticsearch7.x

    2024-07-10 22:14:02       33 阅读
  2. d3tree树控件,点击动态加载,默认展开三层

    2024-07-10 22:14:02       22 阅读
  3. ontape备份异机还原的样例

    2024-07-10 22:14:02       26 阅读
  4. [PaddlePaddle飞桨] PaddleSpeech语言小模型部署

    2024-07-10 22:14:02       30 阅读
  5. vivado DQS_BIAS

    2024-07-10 22:14:02       30 阅读
  6. PHP框架详解-symfony框架

    2024-07-10 22:14:02       30 阅读
  7. 深入理解UTF-8 Encoding在C#中的应用与异常处理

    2024-07-10 22:14:02       30 阅读
  8. Linux 常用命令 - mkdir【创建新目录】

    2024-07-10 22:14:02       26 阅读
  9. stm32实现IIC读写

    2024-07-10 22:14:02       30 阅读
  10. 中小企业和数智化的距离,只差一块华为IdeaHub

    2024-07-10 22:14:02       29 阅读