美文网首页
结构模式-桥接模式(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