Swift解决方案:网桥

我想请您注意抽象汉堡包及其作为餐食的具体实现。 假设我们要添加一个新汉堡,您需要创建多少个其他类?

如果回答三个,那将是正确的:

两个层次

这是不直观的,但是避免这种混乱的解决方案是创建两个单独的层次结构。 这是定义在声明时的含义:

桥接模式将抽象与其实现分离开来……

  1. “抽象”是指基类或协议。 在我们的示例中,它涉及各种汉堡类。 这些汉堡包不会被实例化,因为餐厅不会单独出售它们。 必须使用实现将它们分类为一顿完整的饭菜才能使用。
  2. “实施”是指我们在将汉堡包加入餐边后制作的餐食类。

因此,我们将汉堡包(抽象)与餐食/面食(实现)分离,并剩下两个类层次结构。

层次结构之间的桥梁

然后定义继续说:

桥接模式将抽象与其实现分离, 以便两者可以独立变化。

现在我们有了两个单独的层次结构,我们需要一种连接两者的方法。 为此,我们为每个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() 

我们对桥梁的应用相当简单。 我们只需选择要创建的设备,然后传入任何音频处理程序即可。

结论

轻拍自己的背部! 您现在知道如何:

  1. 有效地应对爆炸性的阶级阶层
  2. 在两个单独的层次结构之间架起一座桥梁

编程工具中已添加了另一个工具! 但是我们还没有停止。 下周检查另一个快速的设计模式!

最初于 2017 年7月29日 发布在 swiftcraft.io 上。