本文大部分内容翻译至《Pro Design Pattern In Swift》By Adam Freeman,一些地方做了些许修改,并将代码升级到了Swift2.0,翻译不当之处望多包涵。
桥接模式(The Bridge Pattern)
桥接模式把事物对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化。事物对象仅是一个抽象的概念。如“圆形”、“三角形”归于抽象的“形状”之下,而“画圆”、“画三角”归于实现行为的“画图”类之下,然后由“形状”调用“画图”。
示例工程
OS X Command Line Tool工程:
Comms.swift
protocol ClearMessageChannel {
func send(message:String)
}
protocol SecureMessageChannel {
func sendEncryptedMessage(encryptedText:String)
}
class Communicator {
private let clearChannel:ClearMessageChannel
private let secureChannel:SecureMessageChannel
init (clearChannel:ClearMessageChannel, secureChannel:SecureMessageChannel) {
self.clearChannel = clearChannel
self.secureChannel = secureChannel
}
func sendCleartextMessage(message:String) {
self.clearChannel.send(message);
}
func sendSecureMessage(message:String) {
self.secureChannel.sendEncryptedMessage(message)
}
}
Communicator提供了允许传送标准信息和安全信息的方法。操作这些信息的机制是 ClearMessageChannel协议和SecureMessageChannel 协议。
这里我们将创建两种不同的网络机制来传输信息:有线传输和无线传输。
Channels.swift
class Landline : ClearMessageChannel {
func send(message: String) {
print("Landline: \(message)")
}
}
class SecureLandLine : SecureMessageChannel {
func sendEncryptedMessage(message: String) {
print("Secure Landline: \(message)")
}
}
class Wireless : ClearMessageChannel {
func send(message: String) {
print("Wireless: \(message)")
}
}
class SecureWireless : SecureMessageChannel {
func sendEncryptedMessage(message: String) {
print("Secure Wireless: \(message)")
}
}
然后我们看main.swift:
main.swift
var clearChannel = Landline()
var secureChannel = SecureLandLine()
var comms = Communicator(clearChannel: clearChannel, secureChannel: secureChannel)
comms.sendCleartextMessage("Hello!")
comms.sendSecureMessage("This is a secret")
运行程序:
Landline: Hello!
Secure Landline: This is a secret
理解桥接模式解决的问题
从上图可以看出,问题在于每一次我们增加一个新的机能或者一个新的平台,都会导致实现类的数量急剧的增加。比如我们再增加一个Chanel,那么实现类将会增加到6个。这就是所谓的类爆炸式层级问题。
理解桥接模式
桥接模式从实现中分离出一个抽象,这样他们都能各自独立的变化。
Tip:分离共通和特定功能是最有效的办法。
在示例中,特定功能是每一个平台使用一个特殊的网络来传输信息,共通功能是传输信息的准备。第一步是定义每一个协议---信息和传输。然后是创建实现类。
实现桥接模式
处理信息
首先我们处理共通功能--信息。
Messages.swift
import Foundation
protocol Message {
init (message:String)
func prepareMessage()
var contentToSend:String { get }
}
class ClearMessage : Message {
private var message:String
required init(message:String) {
self.message = message
}
func prepareMessage() {
// no action required
}
var contentToSend:String {
return message
}
}
class EncryptedMessage : Message {
private var clearText:String
private var cipherText:String?
required init(message:String) {
self.clearText = message
}
func prepareMessage() {
cipherText = String(clearText.characters.reverse())
}
var contentToSend:String {
return cipherText!
}
}
处理传输
Channels.swift
protocol Channel {
func sendMessage(msg:Message)
}
class LandlineChannel : Channel {
func sendMessage(msg: Message) {
print("Landline: \(msg.contentToSend)")
}
}
class WirelessChannel : Channel {
func sendMessage(msg: Message) {
print("Wireless: \(msg.contentToSend)")
}
}
创建桥
最后,我们需要创建一个类来将Communicator类和Message协议,Channel协议连接起来。
Bridge.swift
class CommunicatorBridge : ClearMessageChannel, SecureMessageChannel {
private var channel:Channel
init(channel:Channel) {
self.channel = channel
}
func send(message: String) {
let msg = ClearMessage(message: message);
sendMessage(msg)
}
func sendEncryptedMessage(encryptedText: String) {
let msg = EncryptedMessage(message: encryptedText)
sendMessage(msg)
}
private func sendMessage(msg:Message) {
msg.prepareMessage()
channel.sendMessage(msg)
}
}
最后我们修改main.swift:
main.swift
var bridge = CommunicatorBridge(channel: LandlineChannel())
var comms = Communicator(clearChannel: bridge, secureChannel: bridge)
comms.sendCleartextMessage("Hello!")
comms.sendSecureMessage("This is a secret")
运行程序:
Landline: Hello!
Landline: terces a si sihT
增加新的信息和传输
Comms.swift
protocol ClearMessageChannel {
func send(message:String)
}
protocol SecureMessageChannel {
func sendEncryptedMessage(encryptedText:String)
}
protocol PriorityMessageChannel {
func sendPriority(message:String)
}
class Communicator {
private let clearChannel:ClearMessageChannel
private let secureChannel:SecureMessageChannel
private let priorityChannel:PriorityMessageChannel
init (clearChannel:ClearMessageChannel, secureChannel:SecureMessageChannel, priorityChannel:PriorityMessageChannel) {
self.clearChannel = clearChannel
self.secureChannel = secureChannel
self.priorityChannel = priorityChannel
}
func sendCleartextMessage(message:String) {
self.clearChannel.send(message)
}
func sendSecureMessage(message:String) {
self.secureChannel.sendEncryptedMessage(message)
}
func sendPriorityMessage(message:String) {
self.priorityChannel.sendPriority(message)
}
}
如果不使用桥接模式,那么新增一个信息类型将要增加5个类。请看下图:
而在桥接模式下,添加相同的信息和传输只需要新增两个类。
NewFeatures.swift
class SatelliteChannel : Channel {
func sendMessage(msg: Message) {
print("Satellite: \(msg.contentToSend)")
}
}
class PriorityMessage : ClearMessage {
override var contentToSend:String {
return "Important: \(super.contentToSend)"
}
}
接下来我们更新 Communicator 类:
Bridge.swift
class CommunicatorBridge : ClearMessageChannel, SecureMessageChannel,PriorityMessageChannel{
private var channel:Channel
init(channel:Channel) {
self.channel = channel
}
func send(message: String) {
let msg = ClearMessage(message: message);
sendMessage(msg)
}
func sendEncryptedMessage(encryptedText: String) {
let msg = EncryptedMessage(message: encryptedText)
sendMessage(msg)
}
func sendPriority(message: String) {
sendMessage(PriorityMessage(message: message))
}
private func sendMessage(msg:Message) {
msg.prepareMessage()
channel.sendMessage(msg)
}
}
最后main.swift:
main.swift
var bridge = CommunicatorBridge(channel: SatelliteChannel())
var comms = Communicator(clearChannel: bridge,secureChannel: bridge,
priorityChannel: bridge)
comms.sendCleartextMessage("Hello!")
comms.sendSecureMessage("This is a secret")
comms.sendPriorityMessage("This is important")
运行程序:
Satellite: Hello!
Satellite: terces a si sihT
Satellite: Important: This is important
桥接模式的变形
最简单的变形就是和工厂模式结合,这样特定部分的选择就会被隐藏起来。
Channels.swift
class Channel {
enum Channels {
case Landline
case Wireless
case Satellite
}
class func getChannel(channelType:Channels) -> Channel {
switch channelType {
case .Landline:
return LandlineChannel()
case .Wireless:
return WirelessChannel()
case .Satellite:
return SatelliteChannel()
}
}
func sendMessage(msg:Message) {
fatalError("Not implemented")
}
}
class LandlineChannel : Channel {
override func sendMessage(msg: Message) {
print("Landline: \(msg.contentToSend)")
}
}
class WirelessChannel : Channel {
override func sendMessage(msg: Message) {
print("Wireless: \(msg.contentToSend)")
}
}
然后是NewFeatures.swift
class SatelliteChannel : Channel {
override func sendMessage(msg: Message) {
print("Satellite: \(msg.contentToSend)")
}
}
class PriorityMessage : ClearMessage {
override var contentToSend:String {
return "Important: \(super.contentToSend)"
}
}
修改Bridge.swift中的初始化方法:
Bridge.swift
...
init(channel:Channel.Channels) {
self.channel = Channel.getChannel(channel)
}
...
最后更新main.swift:
var bridge = CommunicatorBridge(channel:Channel.Channels.Satellite)
var comms = Communicator(clearChannel: bridge,secureChannel: bridge,
priorityChannel: bridge)
comms.sendCleartextMessage("Hello!")
comms.sendSecureMessage("This is a secret")
comms.sendPriorityMessage("This is important")
运行程序,得到结果和上面的一样:
Satellite: Hello!
Satellite: terces a si sihT
Satellite: Important: This is important
网友评论