持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情
- 本文主要介绍iOS设计模式中的
中介者模式,中介者模式主要是为了解耦,可以避免各个对象相互引用导致耦合性太强。
1. 什么是中介者模式
在机场我们可以发现飞机都是有条不紊的进行起飞和降落,这都是通过集中的空中交通管制,要是没有管制那么飞机起飞和降落就会变得危险而复杂。我们在开车的过程中,十字路口的红绿灯其实也是扮演着交通管理者,我们可以发现当红绿灯坏的时候,路口交通就变得异常拥堵,过往车辆都要小心通过。
在面向对象软件中,我们在设计中见过很多这样的场景。典型的例子是应用程序中的UI元素。比如有个对话框带有静态文本,列表框,文本框,以及多个输入框。当列表框中的一项被选中时,静态文本会被跟新列表框选定的值。当更多的UI元素参与到这一错综复杂关系时,就会变得难以控制。这个时候就需要一个交通管理员来管理所有的UI交流。
面向对象的设计鼓励把行为分散到不同的对象中。这种分散可能导致对象之间的相互关联。在最糟糕的情况下,所有对象都彼此了解并相互操作。
虽然把行为分散到不同对象增强了可复用性,但是增加的相互关联又减少了获得的益处。增加的关联使得对象很难或不能在不依赖其他对象的情况下工作。中介者模式用于定义一个集中的场所,对象间的交互可以在一个中介者对象中处理。其他对象不必彼此交互,因此减少了它们之间的依存关系。
中介者模式:用一个对象来封装一系列对象的交互方式。中介者使得各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
2. 什么时候使用中介者模式
以下几种常见的情形下,可以考虑使用这一模式。
- 对象间的交互虽
定义明确然而非常复杂,导致一组对彼此相互依赖而且难以理解。 - 因为对象
引用了许多其他对象并与其通讯,导致对象难以复用。 - 想要定制一个分布在多个类中的逻辑或行为,又
不想生成太多子类。
3. 代码展示
可以发现我么通过Mediator中介者持用对象,对象持有中介者,从而达到间接的交互
import XCTest
/// The Mediator interface declares a method used by components to notify the
/// mediator about various events. The Mediator may react to these events and
/// pass the execution to other components.
protocol Mediator: AnyObject {
func notify(sender: BaseComponent, event: String)
}
/// Concrete Mediators implement cooperative behavior by coordinating several
/// components.
class ConcreteMediator: Mediator {
private var component1: Component1
private var component2: Component2
init(_ component1: Component1, _ component2: Component2) {
self.component1 = component1
self.component2 = component2
component1.update(mediator: self)
component2.update(mediator: self)
}
func notify(sender: BaseComponent, event: String) {
if event == "A" {
print("Mediator reacts on A and triggers following operations:")
self.component2.doC()
}
else if (event == "D") {
print("Mediator reacts on D and triggers following operations:")
self.component1.doB()
self.component2.doC()
}
}
}
/// The Base Component provides the basic functionality of storing a mediator's
/// instance inside component objects.
class BaseComponent {
fileprivate weak var mediator: Mediator?
init(mediator: Mediator? = nil) {
self.mediator = mediator
}
func update(mediator: Mediator) {
self.mediator = mediator
}
}
/// Concrete Components implement various functionality. They don't depend on
/// other components. They also don't depend on any concrete mediator classes.
class Component1: BaseComponent {
func doA() {
print("Component 1 does A.")
mediator?.notify(sender: self, event: "A")
}
func doB() {
print("Component 1 does B.\n")
mediator?.notify(sender: self, event: "B")
}
}
class Component2: BaseComponent {
func doC() {
print("Component 2 does C.")
mediator?.notify(sender: self, event: "C")
}
func doD() {
print("Component 2 does D.")
mediator?.notify(sender: self, event: "D")
}
}
/// Let's see how it all works together.
class MediatorConceptual: XCTestCase {
func testMediatorConceptual() {
let component1 = Component1()
let component2 = Component2()
let mediator = ConcreteMediator(component1, component2)
print("Client triggers operation A.")
component1.doA()
print("\nClient triggers operation D.")
component2.doD()
print(mediator)
}
}
执行结果
Client triggers operation A.
Component 1 does A.
Mediator reacts on A and triggers following operations:
Component 2 does C.
Client triggers operation D.
Component 2 does D.
Mediator reacts on D and triggers following operations:
Component 1 does B.
Component 2 does C.
对于一些UI跳转的情况我们也可以使用中介者模式,并让中介者成为单例。
4. 总结
中介者模式降低了对象直接的相互耦合性,和交互性。但是中介者模式以中介者内部的复杂性代替交互的复杂性。因为中介者封装与合并了各个对象的各种协作逻辑,自身可能变得比它们任何一个都复杂。这会让中介者成为无所不知的庞然大物,并且难以维护。这个过程我们可以使用另外一种模式把它分解,比如使用策略模式或者责任链模式。要创造性地混用和组合各种设计模式解决同一个问题。