一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情。
前言
桥接模式介绍
桥接模式和适配器模式一样,本质都是涉及到两个类的协同工作,但是两者侧重点不一样。桥接模式是让新代码进行有效结合,在代码设计阶段就将两个类的层次结构独立开来便于扩展;适配器模式主要还是意在修补扩展旧代码,让两个不兼容的类在一起工作。
定义
桥接模式( Bridge )隶属于结构型,原理主要是通过在两个类之间提供桥接结构将类的抽象元素与其实现分离。两种类型的类都可以在结构上进行更改,而不会相互影响。外部只需要访问抽象部分,具体实现无需关心。
特点
优点
- 在编码设计阶段进行,解耦对象的接口并使其独立。
- 在类的改进方面具备高可扩展性,可以独立扩展(子类化)抽象和实现层次结构。
缺点:
- 系统复杂度上升,对于抽象的能力有一定的要求。
- 设计者和使用者需要有统一的功能理解纬度。
理解实现
现实模型
大家都知道我有一个卖果子的老乡叫阿珍,前段时间阿珍不是买了一台进口的榨汁机嘛,最近阿珍进军了果子汁行业,今天下班我找阿珍买了一杯芒果汁,阿珍三下五除二的给我做了两杯不同地域的芒果汁,我回家喝完写水文。
分析模型
主线:阿珍快速做了两杯不同地域的果汁给我,我喝完写水文。
模型1: 阿珍 -> 消费者
模型2: 地域 -> 抽象角色
模型3:进口/出口水果 -> 扩展的抽象角色
模型4: 水果 -> 抽象实现角色
模型5: 进口/出口芒果 -> 具体实现角色
阿珍(消费者)
class AZhen:MeiNv {
fun main(){
// 阿珍制作进口芒果汁
val importMangoFruit = ImportMangoFruit(ImportFruit())
importMangoFruit.createJuice()
// 阿珍制作国产芒果汁
val domesticMangoFruit = DomesticMangoFruit(DomesticFruit())
domesticMangoFruit.createJuice()
}
}
地域 ( 抽象角色)
interface IAreaFruit{
fun area():String
}
进口/出口水果 (扩展的抽象角色)
// 进口水果
class ImportFruit:IAreaFruit{
fun area():String = "进口"
}
// 国产水果
class DomesticFruit:IAreaFruit{
fun area():String = "国产"
}
水果 (抽象实现角色)
abstract class Fruit{
abstract fun creatJuice()
}
进口/出口芒果 (具体实现角色)
// 进口芒果
class ImportMangoFruit(val iAreaFruit:IAreaFruit):Fruit{
override fun creatJuice(){
iAreaFruit.area()
}
}
// 国产芒果
class DomesticMangoFruit(val iAreaFruit:IAreaFruit):Fruit{
override fun creatJuice(){
iAreaFruit.area()
}
}
使用实例
下面以热敏小票打印业务作为列子进行理解,打印机的类型有多种,打印模板也有多种,两个维度的产品进行组合,这时我们就考虑到使用桥接模式。
商户消费打印
class Merchan{
fun placeDishOder(){
val order = OrderModel("菜品订单数据")
NetPrinter(DishReceipt(),order).print()
BluetoothPrinter(DishReceipt(),order).print()
}
fun placeBillOder(){
val order = OrderModel("结账订单数据")
NetPrinter(BillReceipt(),order).print()
BluetoothPrinter(BillReceipt(),order).print()
}
}
抽象角色和扩展角色
// 小票接口
interface IReceipt{
fun creatReceipt(order:OrderModel):PosTemplate
}
// 结账订单小票
class BillReceipt:IReceipt{
override fun creatReceipt(order:OrderModel):PosTemplate{
println("订单转换结账单模板")
}
}
// 菜品清单小票
class DishReceipt:IReceipt{
override fun creatReceipt(order:OrderModel):PosTemplate{
println("订单转换菜品清单模板")
}
}
抽象实现和具体实现
// 抽象打印机
abstract class BasePrinter{
abstract fun print()
}
// 网络打印机
class NetPrinter(val receipt:IReceipt,val order:OrderModel):BasePrinter{
override fun print(){
receipt.creatReceipt(order)
println("调用网络打印机打印模板")
}
}
// 蓝牙打印机
class BluetoothPrinter:(val receipt:IReceipt,val order:OrderModel):BasePrinter{
override fun print(){
receipt.creatReceipt(order)
println("调用蓝牙打印机打印模板")
}
}
适用环境
- 多个对象之间共享一个实现,而且任何更改都不应影响抽象。
- 您的程序需要实现的运行时绑定。
- 当您想要划分和组织具有某些功能的多个变体的整体类时(例如,如果该类必须与各种数据库服务器一起使用)。
- 当您必须开发一个模块时,该模块可以具有一些继承的属性或行为以及一些动态。
总结
我们在开发过程中往往有很多不确定的因素导致我们并不太清楚功能设计是否完整,那么这时候我们可以考虑使用桥接模式,虽然这样听起来很扯,但是根据上面的学习我们清楚的知道,桥接模式具有极强的灵活性,也不会因为调整而破坏原有结构。