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

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

相关文章

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

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个