设计模式学习之中介者模式

2024-06-24 05:32

本文主要是介绍设计模式学习之中介者模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们平时写代码的过程,一个类必然会与其他类产生依赖关系,如果这种依赖关系如网状般错综复杂,那么必然会影响我们的代码逻辑以及执行效率,适当地使用中介者模式可以对这种依赖关系进行解耦使逻辑结构清晰,本篇博客,我们就一起学习中介者模式。

定义及使用场景

定义:中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使它们可以松散耦合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。

使用场景:
当对象之间的交互操作很多且每个对象的行为操作都依赖彼此时,为防止在修改一个对象的行为时,同时涉及很多其他对象的行为,可使用中介者模式。

UML类图

这里写图片描述

(1)Mediator:抽象中介者角色,定义了同事对象到中介者对象的接口,一般以抽象类的方式实现。

(2)ConcreteMediator:具体中介者角色,继承于抽象中介者,实现了父类定义的方法,它从具体的同事对象接受消息,向具体同事对象发出命令。

(3)Colleague:抽象同事类角色,定义了中介者对象的接口,它只知道中介者而不知道其他的同事对象。

(4)ConcreteColleague1、ConcreteColleague2:具体同事类角色,继承于抽象同事类,每个具体同事类都知道本身在小范围的行为,而不知道在大范围内的目的。

中介者模式通用代码

抽象同事类:
Colleague.class

public abstract class Colleague {protected Mediator mediator;public void setMediator(Mediator mediator) {this.mediator = mediator;}public abstract void operation();
}

具体同事类
ConcreteColleagueA.class && ConcreteColleagueB.class

public class ConcreteColleagueA extends Colleague{public void notifyColleagueB() {mediator.notifyColleagueB();}@Overridepublic void operation() {System.out.print("this is ConcreteColleagueA's operation\n");}
}
public class ConcreteColleagueB extends Colleague{public void notifyColleagueA() {mediator.notifyColleagueA();}@Overridepublic void operation() {System.out.print("this is ConcreteColleagueB's operation\n");}
}

抽象中介者角色:
Mediator.class

public abstract class Mediator {protected Colleague colleagueA;protected Colleague colleagueB;public Mediator(Colleague colleagueA, Colleague colleagueB) {this.colleagueA = colleagueA;this.colleagueB = colleagueB;}public abstract void notifyColleagueA();public abstract void notifyColleagueB();
}

ConcreteMediator.class

public class ConcreteMediator extends Mediator{public ConcreteMediator(Colleague colleagueA, Colleague colleagueB) {super(colleagueA, colleagueB);}@Overridepublic void notifyColleagueA() {if (colleagueA != null) {colleagueA.operation();}}@Overridepublic void notifyColleagueB() {if (colleagueB != null) {colleagueB.operation();}}
}

测试代码:

public class Client {public static void main(String[] args) {Colleague colleagueA = new ConcreteColleagueA();Colleague colleagueB = new ConcreteColleagueB();Mediator mediator = new ConcreteMediator(colleagueA, colleagueB);colleagueA.setMediator(mediator);colleagueB.setMediator(mediator);((ConcreteColleagueA)colleagueA).notifyColleagueB();((ConcreteColleagueB)colleagueB).notifyColleagueA();}
}

两个 Colleague 类成功通过 Mediator 进行了相互作用。上面是中介者模式的标准写法,在平时项目中,硬是将各业务的类抽象出一个 Colleague 父类是不太合理的,因为子类之间的业务逻辑的不同,导致他们很难抽象出一些公用方法,所以这时候使用中介者模式,可以省去 Colleague 这个角色,让 Mediator 直接依赖于几个同事子类;同时也可以不定义Mediator接口,把具体的中介者对象实现成为单例,这样同事对象不再持有中介者,而是在需要的时候直接获取中介者对象并调用;中介者也不再持有同事对象,而是在具体处理方法里面去创建,或获取,或从数据传入需要的同事对象。

中介者模式例子

同事:

//抽象同事类  
abstract class AbstractColleague {  protected AbstractMediator mediator;  /**既然有中介者,那么每个具体同事必然要与中介者有联系,  * 否则就没必要存在于 这个系统当中,这里的构造函数相当  * 于向该系统中注册一个中介者,以取得联系  */ public AbstractColleague(AbstractMediator mediator) {  this.mediator = mediator;  }  // 在抽象同事类中添加用于与中介者取得联系(即注册)的方法  public void setMediator(AbstractMediator mediator) {  this.mediator = mediator;  }  
}  //具体同事A  
class ColleagueA extends AbstractColleague {  //每个具体同事都通过父类构造函数与中介者取得联系  public ColleagueA(AbstractMediator mediator) {  super(mediator);  }  //每个具体同事必然有自己分内的事,没必要与外界相关联  public void self() {  System.out.println("同事A --> 做好自己分内的事情 ...");  }  //每个具体同事总有需要与外界交互的操作,通过中介者来处理这些逻辑并安排工作  public void out() {  System.out.println("同事A --> 请求同事B做好分内工作 ...");  super.mediator.execute("ColleagueB", "self");  }  
}  //具体同事B  
class ColleagueB extends AbstractColleague {  public ColleagueB(AbstractMediator mediator) {  super(mediator);  }  public void self() {  System.out.println("同事B --> 做好自己分内的事情 ...");  }  public void out() {  System.out.println("同事B --> 请求同事A做好分内工作  ...");  super.mediator.execute("ColleagueA", "self");  }  
} 

中介者:

//抽象中介者  
abstract class AbstractMediator {  //中介者肯定需要保持有若干同事的联系方式  protected Hashtable<String, AbstractColleague> colleagues = new Hashtable<String, AbstractColleague>();  //中介者可以动态地与某个同事建立联系  public void addColleague(String name, AbstractColleague c) {  this.colleagues.put(name, c);  }     //中介者也可以动态地撤销与某个同事的联系  public void deleteColleague(String name) {  this.colleagues.remove(name);  }  //中介者必须具备在同事之间处理逻辑、分配任务、促进交流的操作  public abstract void execute(String name, String method);   
}  //具体中介者  
class Mediator extends AbstractMediator{  //中介者最重要的功能,来回奔波与各个同事之间  public void execute(String name, String method) {  if("self".equals(method)){  //各自做好分内事  if("ColleagueA".equals(name)) {  ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");  colleague.self();  }else {  ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");  colleague.self();  }  }else { //与其他同事合作  if("ColleagueA".equals(name)) {  ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");  colleague.out();  }else {  ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");  colleague.out();  }  }  }  
} 

测试类:

//测试类  
public class Client {  public static void main(String[] args) {  //创建一个中介者  AbstractMediator mediator = new Mediator();  //创建两个同事  ColleagueA colleagueA = new ColleagueA(mediator);  ColleagueB colleagueB = new ColleagueB(mediator);  //中介者分别与每个同事建立联系  mediator.addColleague("ColleagueA", colleagueA);  mediator.addColleague("ColleagueB", colleagueB);  //同事们开始工作  colleagueA.self();  colleagueA.out();  System.out.println("======================合作愉快,任务完成!\n");  colleagueB.self();  colleagueB.out();  System.out.println("======================合作愉快,任务完成!");  }  
} 

具体中介者类Mediator中的execute()方法中现在就有一堆冗长的判断代码了。虽然可以把它分解并增加到Mediator类中的其它private方法中,但是具体的业务逻辑是少不了的。

所以,在解耦同事类之间的联系的同时,中介者自身也不免任务过重,因为几乎所有的业务逻辑都交代到中介者身上了,这就是中介者模式的不足之处。

对上面的例子还可以进行如下优化:
修改后的同事

//抽象同事类  
abstract class AbstractColleague {  protected AbstractMediator mediator;      //舍去在构造函数中建立起与中介者的联系  
//  public AbstractColleague(AbstractMediator mediator) {  
//      this.mediator = mediator;  
//  }  // 在抽象同事类中添加用于与中介者取得联系(即注册)的方法  public void setMediator(AbstractMediator mediator) {  this.mediator = mediator;  }  
}  //具体同事A  
class ColleagueA extends AbstractColleague {  //舍去在构造函数中建立起与中介者的联系  
//  public ColleagueA(AbstractMediator mediator) {  
//      super(mediator);  
//  }  //每个具体同事必然有自己分内的事,没必要与外界相关联  public void self() {  System.out.println("同事A --> 做好自己分内的事情 ...");  }  //每个具体同事总有需要与外界交互的操作,通过中介者来处理这些逻辑并安排工作  public void out() {  System.out.println("同事A --> 请求同事B做好分内工作 ...");  super.mediator.execute("ColleagueB", "self");  }  
}  //具体同事B  
class ColleagueB extends AbstractColleague {  //舍去在构造函数中建立起与中介者的联系  
//  public ColleagueB(AbstractMediator mediator) {  
//      super(mediator);  
//  }  public void self() {  System.out.println("同事B --> 做好自己分内的事情 ...");  }  public void out() {  System.out.println("同事B --> 请求同事A做好分内工作  ...");  super.mediator.execute("ColleagueA", "self");  }  
} 

修改后的中介者:

//抽象中介者  
abstract class AbstractMediator {  //中介者肯定需要保持有若干同事的联系方式  protected Hashtable<String, AbstractColleague> colleagues = new Hashtable<String, AbstractColleague>();  //中介者可以动态地与某个同事建立联系  public void addColleague(String name, AbstractColleague c) {  // 在中介者这里帮助具体同事建立起于中介者的联系  c.setMediator(this);  this.colleagues.put(name, c);  }     //中介者也可以动态地撤销与某个同事的联系  public void deleteColleague(String name) {  this.colleagues.remove(name);  }  //中介者必须具备在同事之间处理逻辑、分配任务、促进交流的操作  public abstract void execute(String name, String method);   
} 

测试类


public class Client {  public static void main(String[] args) {  //创建一个中介者  AbstractMediator mediator = new Mediator();  //不用构造函数为具体同事注册中介者来取得联系了  
//      ColleagueA colleagueA = new ColleagueA(mediator);  
//      ColleagueB colleagueB = new ColleagueB(mediator);  ColleagueA colleagueA = new ColleagueA();  ColleagueB colleagueB = new ColleagueB();  //中介者分别与每个同事建立联系  mediator.addColleague("ColleagueA", colleagueA);  mediator.addColleague("ColleagueB", colleagueB);  //同事们开始工作  colleagueA.self();  colleagueA.out();  System.out.println("======================合作愉快,任务完成!\n");  colleagueB.self();  colleagueB.out();  System.out.println("======================合作愉快,任务完成!");  }  
} 

Android源码中的模式实现

Android Mediator样例:—KeyguardViewMediator
关键代码:
同事角色:
KeyguardService:

./base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
public class KeyguardService extends Service {//中介者角色private KeyguardViewMediator mKeyguardViewMediator;@Overridepublic void onCreate() {((SystemUIApplication) getApplication()).startServicesIfNeeded();//中介者角色初始化mKeyguardViewMediator =((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);}private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {@Override // Binder interfacepublic void addStateMonitorCallback(IKeyguardStateCallback callback) {checkPermission();//调用中介者角色mKeyguardViewMediator.addStateMonitorCallback(callback);}@Override // Binder interfacepublic void verifyUnlock(IKeyguardExitCallback callback) {checkPermission();//调用中介者角色mKeyguardViewMediator.verifyUnlock(callback);}......@Overridepublic void onActivityDrawn() {checkPermission();//调用中介者角色mKeyguardViewMediator.onActivityDrawn();}};}

同事角色:
FingerprintUnlockController:

./base/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {//中介者角色private KeyguardViewMediator mKeyguardViewMediator;@Overridepublic void onFingerprintAuthenticated(int userId) {......       switch (mMode) {...... case MODE_WAKE_AND_UNLOCK:...... //调用角色者模式mKeyguardViewMediator.onWakeAndUnlocking();...... }
}

中介者:KeyguardViewMediator
KeyguardViewMediator类充当了一个中介者角色,以对各个角色的通信进行协调。

还有诸如MVP模式中的presenter,还有Binder也都采用了中介者模式

总结

1.优点

(1)适当地使用中介者模式可以避免同事类之间的过度耦合,使得各同事类之间可以相对独立地使用。

(2)使用中介者模式可以将对象的行为和协作进行抽象,能够比较灵活的处理对象间的相互作用。

(3)使用中介者模式可以将对象间多对多的关联转变为一对多的关联,使对象间的关系易于理解和维护。

2.缺点

中介者模式是一种比较常用的模式,也是一种比较容易被滥用的模式。对于大多数的情况,同事类之间的关系不会复杂到混乱不堪的网状结构,因此,大多数情况下,将对象间的依赖关系封装的同事类内部就可以的,没有必要非引入中介者模式。滥用中介者模式,只会让事情变的更复杂。所以,我们决定使用中介者模式之前要多方考虑、权衡利弊。

这篇关于设计模式学习之中介者模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

C#原型模式之如何通过克隆对象来优化创建过程

《C#原型模式之如何通过克隆对象来优化创建过程》原型模式是一种创建型设计模式,通过克隆现有对象来创建新对象,避免重复的创建成本和复杂的初始化过程,它适用于对象创建过程复杂、需要大量相似对象或避免重复初... 目录什么是原型模式?原型模式的工作原理C#中如何实现原型模式?1. 定义原型接口2. 实现原型接口3

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

大数据spark3.5安装部署之local模式详解

《大数据spark3.5安装部署之local模式详解》本文介绍了如何在本地模式下安装和配置Spark,并展示了如何使用SparkShell进行基本的数据处理操作,同时,还介绍了如何通过Spark-su... 目录下载上传解压配置jdk解压配置环境变量启动查看交互操作命令行提交应用spark,一个数据处理框架

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06