美文网首页
结构模式-桥接模式(The Bridge Pattern)

结构模式-桥接模式(The Bridge Pattern)

作者: ZhouMac | 来源:发表于2016-04-13 06:33 被阅读95次

本文大部分内容翻译至《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

相关文章

网友评论

      本文标题:结构模式-桥接模式(The Bridge Pattern)

      本文链接:https://www.haomeiwen.com/subject/lbkwlttx.html