2023跟我学规划形式:中介者形式(Intermediary)

操控器IntermediaryControllerMediator

中介者形式是一种行为规划形式, 能让你削减目标之间紊乱无序的依靠联系。 该形式会约束目标之间的直接交互, 迫使它们经过一个中介者目标进行协作。

遇到的问题

假如你有一个创建和修正客户资料的对话框, 它由各种控件组成, 例如文本框 (TextField)、 复选框 (Checkbox) 和按钮 (Button) 等。

2023跟我学设计模式:中介者模式(Intermediary)

用户界面中各元素间的联系会随程序开展而变得紊乱。

某些表单元素或许会直接进行互动。 例如, 选中 “我有一只狗” 复选框后或许会显示一个躲藏文本框用于输入狗狗的名字。 另一个比如是提交按钮有必要在保存数据前校验一切输入内容。

2023跟我学设计模式:中介者模式(Intermediary)

元素间存在许多关联。 因而, 对某些元素进行修正或许会影响其他元素。

假如直接在表单元素代码中完成事务逻辑, 你将很难在程序其他表单中复用这些元素类。 例如, 因为复选框类与狗狗的文本框相耦合, 所以将无法在其他表单中运用它。 你要么运用渲染资料表单时用到的一切类, 要么一个都不用。

解决方案

中介者形式建议你中止组件之间的直接沟通并使其彼此独立。 这些组件有必要调用特殊的中介者目标, 经过中介者目标重定向调用行为, 以直接的办法进行协作。 最终, 组件仅依靠于一个中介者类, 无需与多个其他组件相耦合。

在资料修正表单的比如中, 对话框 (Dialog) 类自身将作为中介者, 其很或许已知自己一切的子元素, 因而你甚至无需在该类中引入新的依靠联系。

2023跟我学设计模式:中介者模式(Intermediary)

UI 元素有必要经过中介者目标进行直接沟通。

绝大部分重要的修正都在实践表单元素中进行。 让我们想想提交按钮。 之前, 当用户点击按钮后, 它有必要对一切表单元素数值进行校验。 而现在它的唯一作业是将点击事情告诉给对话框。 收到告诉后, 对话框能够自行校验数值或将使命委派给各元素。 这样一来, 按钮不再与多个表单元素相关联, 而仅依靠于对话框类。

你还可认为一切类型的对话框抽取通用接口, 进一步削弱其依靠性。 接口中将声明一个一切表单元素都能运用的告诉办法, 可用于将元素中发生的事情告诉给对话框。 这样一来, 一切完成了该接口的对话框都能运用这个提交按钮了。

选用这种办法, 中介者形式让你能在单个中介者目标中封装多个目标间的杂乱联系网。 类所具有的依靠联系越少, 就越易于修正、 扩展或复用。

实在世界类比

2023跟我学设计模式:中介者模式(Intermediary)

飞行器驾驶员之间不会经过彼此沟通来决定下一架下降的飞机。 一切沟通都经过操控塔台进行。

飞行器驾驶员们在接近或脱离空中控制区域时不会直接彼此沟通。 但他们会与飞机跑道邻近, 塔台中的空管员通话。 假如没有空管员, 驾驶员就需求留意机场邻近的一切飞机, 并与数十位飞行员组成的委员会评论下降次序。 那恐怕会让飞机坠毁的统计数据一飞冲天吧。

塔台无需控制飞行全程, 只需在航站区加强管控即可, 因为该区域的决议计划参与者数量关于飞行员来说实在太多了。

中介者形式结构

2023跟我学设计模式:中介者模式(Intermediary)

  1. 组件 (Component) 是各种包括事务逻辑的类。 每个组件都有一个指向中介者的引证, 该引证被声明为中介者接口类型。 组件不知道中介者实践所属的类, 因而你可经过将其衔接到不同的中介者以使其能在其他程序中复用。

  2. 中介者 (Mediator) 接口声明晰与组件沟通的办法, 但一般仅包括一个告诉办法。 组件可将任意上下文 (包括自己的目标) 作为该办法的参数, 只有这样接纳组件和发送者类之间才不会耦合。

  3. 详细中介者 (Concrete Mediator) 封装了多种组件间的联系。 详细中介者一般会保存一切组件的引证并对其进行管理, 甚至有时会对其生命周期进行管理。

  4. 组件并不知道其他组件的状况。 假如组件内发生了重要事情, 它只能告诉中介者。 中介者收到告诉后能轻易地确认发送者, 这或许已足以判断接下来需求触发的组件了。

    关于组件来说, 中介者看上去彻底便是一个黑箱。 发送者不知道最终会由谁来处理自己的恳求, 接纳者也不知道最初是谁发出了恳求。

伪代码

在本例中, 中介者形式可帮助你削减各种 UI 类 (按钮、 复选框和文本标签) 之间的彼此依靠联系。

2023跟我学设计模式:中介者模式(Intermediary)

UI 对话框类的结构

用户触发的元素不会直接与其他元素沟通, 即使看上去它们应该这样做。 相反, 元素只需让中介者知晓事情即可, 并能在发出告诉时一起传递任何上下文信息。

本例中的中介者是整个认证对话框。 对话框知道详细元素应如何进行协作并促进它们的直接沟通。 当接纳到事情告诉后, 对话框会确认担任处理事情的元素并据此重定向恳求。

中介者形式适合运用场景

当一些目标和其他目标严密耦合致使难以对其进行修正时, 可运用中介者形式。

该形式让你将目标间的一切联系抽取成为一个独自的类, 以使关于特定组件的修正作业独立于其他组件。

当组件因过于依靠其他组件而无法在不同运用中复用时, 可运用中介者形式。

运用中介者形式后, 每个组件不再知晓其他组件的状况。 尽管这些组件无法直接沟通, 但它们仍可经过中介者目标进行直接沟通。 假如你期望在不同运用中复用一个组件, 则需求为其供给一个新的中介者类。

假如为了能在不同情形下复用一些基本行为, 导致你需求被逼创建大量组件子类时, 可运用中介者形式。

因为一切组件间联系都被包括在中介者中, 因而你无需修正组件就能方便地新建中介者类以界说新的组件协作办法。

完成办法

  1. 找到一组当前严密耦合, 且供给其独立功能带来更大好处的类 (例如更易于保护或更方便复用)。

  2. 声明中介者接口并描述中介者和各种组件之间所需的沟通接口。 在绝大多数状况下, 一个接纳组件告诉的办法就足够了。

    假如你期望在不同情形下复用组件类, 那么该接口将非常重要。 只需组件运用通用接口与其中介者协作, 你就能将该组件与不同完成中的中介者进行衔接。

  3. 完成详细中介者类。 该类可从自行保存其下一切组件的引证中获益。

  4. 你能够更进一步, 让中介者担任组件目标的创建和毁掉。 此后, 中介者或许会与工厂或外观类似。

  5. 组件有必要保存关于中介者目标的引证。 该衔接一般在组件的构造函数中树立, 该函数会将中介者目标作为参数传递。

  6. 修正组件代码, 使其可调用中介者的告诉办法, 而非其他组件的办法。 然后将调用其他组件的代码抽取到中介者类中, 并在中介者接纳到该组件告诉时执行这些代码。

中介者形式优缺点

  • 单一职责原则。 你能够将多个组件间的沟通抽取到同一位置, 使其更易于理解和保护。

  • 开闭原则。 你无需修正实践组件就能增加新的中介者。

  • 你能够减轻运用中多个组件间的耦合状况。

  • 你能够更方便地复用各个组件。

  • 一段时间后, 中介者或许会演化成为[上帝目标]。

代码示例

  • Go 中介者形式讲解和代码示例 – 掘金 ()