Swift解决方案:网桥
我想请您注意抽象汉堡包及其作为餐食的具体实现。 假设我们要添加一个新汉堡,您需要创建多少个其他类?
如果回答三个,那将是正确的:
两个层次
这是不直观的,但是避免这种混乱的解决方案是创建两个单独的层次结构。 这是定义在声明时的含义:
桥接模式将抽象与其实现分离开来……
- “抽象”是指基类或协议。 在我们的示例中,它涉及各种汉堡类。 这些汉堡包不会被实例化,因为餐厅不会单独出售它们。 必须使用实现将它们分类为一顿完整的饭菜才能使用。
- “实施”是指我们在将汉堡包加入餐边后制作的餐食类。
因此,我们将汉堡包(抽象)与餐食/面食(实现)分离,并剩下两个类层次结构。
层次结构之间的桥梁
然后定义继续说:
桥接模式将抽象与其实现分离, 以便两者可以独立变化。
现在我们有了两个单独的层次结构,我们需要一种连接两者的方法。 为此,我们为每个Burger
赋予Side
类型的属性。 这种“具有”关系是连接两个层次结构的“桥梁”。
我们这样做是为了使两者可以独立变化。 换句话说,我们不再需要为汉堡和面包的每个组合创建一个类。 由于它们的层次结构是分开的,因此每个新汉堡或一面只需要一个新类。
这一切似乎有点抽象,所以让我们回到代码中进行演示。
编码解决方案
我们需要针对设备和音频类型的单独层次结构。 让我们从音频类型开始:
protocol AudioHandling { func handle(audio: Audio) -> Audio } class AudioEncryptor: AudioHandling { func handle(audio: Audio) -> Audio { // Encrypt and return Audio } } class PlainAudioHandler: AudioHandling { func handle(audio: Audio) -> Audio { // return default audio } }
我们创建一个AudioHandling
协议,每个符合的类都将重点放在准备音频以供设备发送上。
现在,让我们重新实现我们的设备:
class CellPhone: AudioCommunicationsDevice { let audioHandler: AudioHandling init(audioHandler: AudioHandling) { super.init() self.audioHandler = audioHandler } override func sendAudio() { // Use audioHandler(audio:) to prepare audio, then send audio } } class WalkieTalkie: AudioCommunicationsDevice { let audioHandler: AudioHandling init(audioHandler: AudioHandling) { super.init() self.audioHandler = audioHandler } override func sendAudio() { // Use audioHandler(audio:) to prepare audio, then send audio } }
我们为每个设备提供了一个audioHandler
属性,该属性使我们的设备可以“桥接”并处理所有AudioHandling
类型。
这是反映我们的代码的更新后的视觉效果:
行动中的桥梁
这是一个如何使用桥接模式的简短示例:
let audioHandler = AudioEncryptor() let walkieTalkie = WalkieTalkie(audioHandler: audioHandler) walkieTalkie.sendAudio()
我们对桥梁的应用相当简单。 我们只需选择要创建的设备,然后传入任何音频处理程序即可。
结论
轻拍自己的背部! 您现在知道如何:
- 有效地应对爆炸性的阶级阶层
- 在两个单独的层次结构之间架起一座桥梁
编程工具中已添加了另一个工具! 但是我们还没有停止。 下周检查另一个快速的设计模式!
最初于 2017 年7月29日 发布在 swiftcraft.io 上。