持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
- 本文主要介绍iOS设计模式中的桥接模式,就是通过桥接把
抽象类实现部分进行分离通过桥接进行连接使用,比如我们Swift项目使用OC代码就说通过桥接,导入我们要使用的OC类。
1. 什么是桥接模式
我们以遥控器和电视为例,通常来说遥控器切换频道和调节声音都是相同的,但是对于一些拓展功能我们只用在遥控器添加一些按键即可。遥控器基类声明了一个指向设备对象的引用成员变量。 所有遥控器通过通用设备接口与设备进行交互, 使得同一个遥控器可以支持不同类型的设备。
你可以开发独立于设备类的遥控器类, 只需新建一个遥控器子类即可。 例如, 基础遥控器可能只有两个按钮, 但你可在其基础上扩展新功能, 比如额外的一节电池或一块触摸屏。
桥接模式的目的是把抽象层次结构从起实现中分离出来,使其能够独立变更。抽象层定义了供客户端使用的上层的抽象接口。实现层次结构定义了供抽象层次使用的底层接口。实现类的引用被封装于抽象层的实例中时,桥接就形成了。
桥接模式:将抽象部分与它的实现部分分离,使他们都可以独立的变化。
2. 何时使用桥接模式
下面的情况下,自然会想到使用这一模式:
- 不想在
抽象与现实之间形成固定的绑定关系(这样可以在运行时切换实现) - 抽象及其实现都应可以通过
子类化独立进行拓展。 -
对抽象的实现进行修改不应影响客户端代码 - 如果每个实现需要额外的
子类以细化抽象,则说明有必要把他们分成2个部分 - 想在带有不同抽象接口的多个对象之间
共享一个实现。
3.代码展示
import XCTest
/// The Abstraction defines the interface for the "control" part of the two
/// class hierarchies. It maintains a reference to an object of the
/// Implementation hierarchy and delegates all of the real work to this object.
class Abstraction {
fileprivate var implementation: Implementation
init(_ implementation: Implementation) {
self.implementation = implementation
}
func operation() -> String {
let operation = implementation.operationImplementation()
return "Abstraction: Base operation with:\n" + operation
}
}
/// You can extend the Abstraction without changing the Implementation classes.
class ExtendedAbstraction: Abstraction {
override func operation() -> String {
let operation = implementation.operationImplementation()
return "ExtendedAbstraction: Extended operation with:\n" + operation
}
}
/// The Implementation defines the interface for all implementation classes. It
/// doesn't have to match the Abstraction's interface. In fact, the two
/// interfaces can be entirely different. Typically the Implementation interface
/// provides only primitive operations, while the Abstraction defines higher-
/// level operations based on those primitives.
protocol Implementation {
func operationImplementation() -> String
}
/// Each Concrete Implementation corresponds to a specific platform and
/// implements the Implementation interface using that platform's API.
class ConcreteImplementationA: Implementation {
func operationImplementation() -> String {
return "ConcreteImplementationA: Here's the result on the platform A.\n"
}
}
class ConcreteImplementationB: Implementation {
func operationImplementation() -> String {
return "ConcreteImplementationB: Here's the result on the platform B\n"
}
}
/// Except for the initialization phase, where an Abstraction object gets linked
/// with a specific Implementation object, the client code should only depend on
/// the Abstraction class. This way the client code can support any abstraction-
/// implementation combination.
class Client {
// ...
static func someClientCode(abstraction: Abstraction) {
print(abstraction.operation())
}
// ...
}
/// Let's see how it all works together.
class BridgeConceptual: XCTestCase {
func testBridgeConceptual() {
// The client code should be able to work with any pre-configured
// abstraction-implementation combination.
let implementation = ConcreteImplementationA()
Client.someClientCode(abstraction: Abstraction(implementation))
let concreteImplementation = ConcreteImplementationB()
Client.someClientCode(abstraction: ExtendedAbstraction(concreteImplementation))
}
}
执行结果
Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A
ExtendedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B
4. 总结
桥接模式主要是分离抽象层和实现层的对立,个人认为是适配器的进一步分离。适配器本身就是支持某一种实现,为了适配其他类的实现从而通过代理协议来实现,或者block和闭包。而适配器则是完全的分离。所以当陷入困境,苦于“如何从实现中把抽象分离出来而又要让他们联系在一起”之时,凭直觉就会想到桥接模式,我们可以根据理解,看着怎么用于自己的代码。桥接模式可以将庞杂类拆分为几个类层次结构。 此后, 你可以修改任意一个类层次结构而不会影响到其他类层次结构。 这种方法可以简化代码的维护工作, 并将修改已有代码的风险降到最低。