结构型模式-桥接模式
什么是桥接模式
桥接是一种结构型设计模式, 可将一个大类或一系列紧密 相关的类拆分为抽象和实现 两个独立的层次结构,从而 能在开发时分别使用。
- 抽象部分(Abstraction)提供高层控制逻辑,依赖于完成底 层实际工作的实现对象。
- . 实现部分(Implementation)为所有具体实现声明通用接口。 抽象部分仅能通过在这里声明的方法与实现对象交互。抽象部分可以列出和实现部分一样的方法,但是抽象部分通 常声明一些复杂行为,这些行为依赖于多种由实现部分声明 的原语操作
- 具体实现(Concrete Implementations)中包括特定于平台的代码
- 精确抽象(Refined Abstraction)提供控制逻辑的变体。与其父类一样,它们通过通用实现接口与不同的实现进行交互
- 通常情况下,客户端(Client)仅关心如何与抽象部分合作。 但是,客户端需要将抽象对象与一个实现对象连接起来
Example
抽象
package main
type Computer interface { Print() SetPrinter(Printer) }
|
精准抽象a
package main
import "fmt"
type Mac struct { printer Printer }
func (m *Mac) Print() { fmt.Println("Print request for mac") m.printer.PrintFile() }
func (m *Mac) SetPrinter(p Printer) { m.printer = p }
|
精准抽象b
package main
import "fmt"
type Windows struct { printer Printer }
func (w *Windows) Print() { fmt.Println("Print request for windows") w.printer.PrintFile() }
func (w *Windows) SetPrinter(p Printer) { w.printer = p }
|
实施
package main
type Printer interface { PrintFile() }
|
具体实施a
package main
import "fmt"
type Epson struct { }
func (p *Epson) PrintFile() { fmt.Println("Printing by a EPSON Printer") }
|
具体实施b
package main
import "fmt"
type Hp struct { }
func (p *Hp) PrintFile() { fmt.Println("Printing by a HP Printer") }
|
客户端
package main
import "fmt"
func main() {
hpPrinter := &Hp{} epsonPrinter := &Epson{}
macComputer := &Mac{}
macComputer.SetPrinter(hpPrinter) macComputer.Print() fmt.Println()
macComputer.SetPrinter(epsonPrinter) macComputer.Print() fmt.Println()
winComputer := &Windows{}
winComputer.SetPrinter(hpPrinter) winComputer.Print() fmt.Println()
winComputer.SetPrinter(epsonPrinter) winComputer.Print() fmt.Println() }
|
适用场景
- 如果你想要拆分或重组一个具有多重功能的庞杂类(例如能 与多个数据库服务器进行交互的类),可以使用桥接模式。
- 类的代码行数越多,弄清其运作方式就越困难,对其进行修 改所花费的时间就越长。一个功能上的变化可能需要在整个 类范围内进行修改,而且常常会产生错误,甚至还会有一些 严重的副作用
- 如果你希望在几个独立维度上扩展一个类,可使用该模式
- 桥接建议将每个维度抽取为独立的类层次。初始类将相关工 作委派给属于对应类层次的对象,无需自己完成所有工作
- 如果你需要在运行时切换不同实现方法,可使用桥接模式
- 当然并不是说一定要实现这一点,桥接模式可替换抽象部分 中的实现对象,具体操作就和给成员变量赋新值一样简单
优缺点
优点
- 可以创建与平台无关的类和程序
- 客户端代码仅与高层抽象部分进行互动,不会接触到平台的 详细信息
- 开闭原则。你可以新增抽象部分和实现部分,且它们之间不 会相互影响
- 单一职责原则。抽象部分专注于处理高层逻辑,实现部分处 理平台细节
缺点
与其他模式的关系
- 桥接通常会于开发前期进行设计,使你能够将程序的各个部 分独立开来以便开发。另一方面,适配器通常在已有程序中 使用,让相互不兼容的类能很好地合作
- 桥接、状态和策略(在某种程度上包括适配器)模式的接口 非常相似。实际上,它们都基于组合模式——即将工作委派 给其他对象,不过也各自解决了不同的问题。模式并不只是 以特定方式组织代码的配方,你还可以使用它们来和其他开 发者讨论模式所解决的问题。
- 你可以将抽象工厂和桥接搭配使用。如果由桥接定义的抽象 只能与特定实现合作,这一模式搭配就非常有用。在这种情 况下,抽象工厂可以对这些关系进行封装,并且对客户端代 码隐藏其复杂性
- 你可以结合使用生成器和桥接模式: 主管类负责抽象工作, 各种不同的生成器负责实现工作。