前言

桥接模式也称为桥梁模式,是结构型设计模式之一;

定义:将抽象部分与实现部分分离,使它们都可以独立地进行变化;

使用场景:

  • 如果一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,可以通过桥接模式使它们在抽象层建立一个关联关系;
  • 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,也可以考虑使用桥接模式;
  • 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展;

UML类图:

android bridge网桥 android 桥接模式_android bridge网桥


Abstraction:抽象部分,该类保持一个对实现部分对象的引用,抽象部分中的方法需要调用实现部分的对象来实现,该类一般为抽象类;

RefinedAbstraction:优化的抽象部分,抽象部分的具体实现,该类一般是对抽象部分的方法进行完善和扩展;

Implementor:实现部分,可以为接口或抽象类,其方法不一定要与抽象部分中的一致,一般情况下是由实现部分提供基本的操作,而抽象部分定义的则是基于实现部分这些基本操作的业务方法;

ConcreteImplementorA、ConcreteImplemetorB:实现部分的具体实现,完善实现部分中方法定义的具体逻辑;

Client:客户类,客户端程序;

示例代码

这里以喝咖啡进行举例,咖啡可以简单分为4类,大杯加糖、大杯不加糖、小杯加糖、小杯不加糖,实际上对应两种变化,一个是大杯小杯,一个是加糖与不加糖,下面我们使用桥接模式来实现:

  • 定义咖啡添加类,相当于Implementor角色,CoffeeAdd
/**
 * 咖啡添加类,相当于Implementor角色
 */
interface CoffeeAdd {

    /**
     * 具体添加什么由子类实现
     */
    fun add(): String
}
  • 定义加糖类,相当于ConcreteImplement角色,Sugar
/**
 * 加糖,相当于ConcreteImplement角色
 */
class Sugar : CoffeeAdd {
    override fun add(): String {
        return "加糖"
    }
}
  • 定义原味类,相当于ConcreteImplement角色,Ordinary
/**
 * 原味,相当于ConcreteImplement角色
 */
class Ordinary : CoffeeAdd {
    override fun add(): String {
        return "不加糖"
    }
}
  • 定义咖啡类,相当于Abstraction角色,Coffee
/**
 * 咖啡类,相当于Abstraction角色
 */
abstract class Coffee(private val coffeeAdd: CoffeeAdd) {
    /**
     * 制作咖啡,具体什么样的咖啡由子类决定
     */
    abstract fun makeCoffee()
}
  • 定义大杯咖啡类,相当于RefinedAbstraction角色
/**
 * 生产大杯咖啡,相当于RefinedAbstraction角色
 */
class LargeCoffee(private val coffeeAdd: CoffeeAdd) : Coffee(coffeeAdd) {
    override fun makeCoffee() {
        println("大杯${coffeeAdd.add()}咖啡")
    }
}
  • 定义小杯咖啡类,相当于RefinedAbstraction角色
class SmallCoffee(private val coffeeAdd: CoffeeAdd) : Coffee(coffeeAdd) {
    override fun makeCoffee() {
        println("小杯${coffeeAdd.add()}咖啡")
    }
}
  • 编写测试类进行验证
object Test {

    @JvmStatic
    fun main(args: Array<String>) {
        /**
         * 构造加糖不加糖
         */
        val sugar = Sugar()
        val ordinary = Ordinary()

        /**
         * 生产大杯加糖咖啡
         */
        val largeCoffee = LargeCoffee(sugar)
        largeCoffee.makeCoffee()

        /**
         * 生产小杯不加糖咖啡
         */
        val smallCoffee = SmallCoffee(ordinary)
        smallCoffee.makeCoffee()
    }
}

结果输出:

大杯加糖咖啡
小杯不加糖咖啡

Android源码中的桥接模式

  • Window与WindowManager
  • android bridge网桥 android 桥接模式_设计模式_02

  • 其中WindowPhoneWindow构成窗口的抽象部分,Window为抽象部分的接口,PhoneWindow为抽象部分的具体实现以及扩展,而WindowManager则为实现部分的基类,WindowManagerImpl为实现部分具体的逻辑实现,它使用WindowMangerGlobal通过IWindowManager接口与WMS进行通信,最终由WMS完成具体窗口的管理工作;典型的桥接涉及模式!

总结

优点: 分离抽象与实现、灵活的扩展以及对客户来说透明的实现;

缺点: 不容易设计,对开发者来说要把握住抽象与实现的分离;