一周两个设计模式—设计模式之桥接模式(第三周)

715 阅读4分钟

业务背景:

天庭万年单身狗哮天犬为天地咖啡厅开发了一套点咖啡的系统,项目初期项目负责人托塔李天王明确表示,咱们天庭家大业大 只会提供,大杯咖啡,口味只有原味和加糖,不会有第三种选择(嚣张!!) 哮天犬听后,说简单,于是出现了下面的代码

interface Coffee{
     fun orderCoffee(count:Int)
 }

class CoffeeOriginal:Coffee{
    fun orderCoffee(count:Int){
    Log.v("========","点了原味咖啡$count杯)
    }
 }

 class CoffeeSuger:Coffee{
    fun orderCoffee(count:Int){
    Log.v("========","点了加糖咖啡$count杯)
    }
 }

上线,运行,正常,就等着奖金给主人了,哮天犬一脸高兴。

没几天,天王来了告诉哮天犬“小犬啊,你知道的,前两天有只猴子来店里,非得要中杯加牛奶的咖啡,咱们又不提供,就和 猴子吵起来了,后续就动手了,没想到猴子这么厉害,差点把咖啡馆给拆了,老大生气了,说必须得加上中杯和小杯,不加尾款就没有了。“。哮天犬一想不就是加个中杯和小杯吗?好说,看我的厉害。

class  CoffeeOriginalMiddle:Coffee{
  fun orderCoffee(count:Int){
  Log.v("========","点了原味咖啡$count杯)
  }
}

class  CoffeeOriginalSmall:Coffee{
  fun orderCoffee(count:Int){
  Log.v("========","点了原味咖啡$count杯)
  }
}

正写着呢,犬子突然感觉背后一凉,转头一看,主人正冷冷的看着自己,然后耳边传来一个虚无缥缈的声音,你这得加3*2个类啊,要是后续 要加超大杯、巧克力、牛奶、酸奶、蜂蜜、迷你杯、单身狗杯、三眼杯,你怎么维护,你这个类的数量还不得爆炸吗?

还真是这样,还真是这样,该怎么办呢?犬子正在着急,突然灵光一闪,可以抱大腿啊,于是二话不说直接抱腿、 抬头、可怜楚楚、眼含热泪的看着三眼,一言不发。

三眼叹了一口气,谁让自己是个铲屎官呢,留下一句今天的主角:桥接模式。

定义:

    桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interfce)模式。 
    它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

使用场景:

  一个类存在两个独立变化的维度,并且这两个维度都需要进行扩展。对于两个独立变化的维度,使用桥接模式再适合不过了

查完之后,感叹不愧是主人,就是厉害,修改代码。

味道抽离:

interface Taste {
  fun addTaste()

  fun getTaste():String
}

咖啡抽离:

abstract class Coffee(taste: Taste) {
    protected  var taste = taste
   abstract fun orderCoffee(count:Int)
}

大杯:

class LargeCoffee(taste: Taste):Coffee(taste) {
    override fun orderCoffee(count: Int) {
        Log.v("=======","${count}杯大杯的${taste.getTaste()}的咖啡")
    }
}

牛奶:

class MilkTaste:Taste {
    override fun addTaste() {
       Log.v("=========","加牛奶的")
    }

    override fun getTaste():String{
        return "加奶"
    }
}

由此可以创建不同的味道和大小的咖啡了,核心代码就是

abstract class Coffee(taste: Taste) {
     protected  var taste = taste

     abstract fun orderCoffee(count:Int)
}

这样就有了Taste的引用了,通过构造函数注入,这就是桥接的过程,感觉与委托者类似,我们通过 这个引用就可以调用口味的方法了,就把杯子的大小和口味组合起来了。 这样单独的扩展都不会对项目结构产生影响了。

哮天犬把项目写完,天王愉快的给了尾款4000两黄金,给了主人3990,主人开心的去找嫦娥仙子聊仙生理想去了, 而小犬拿着剩余的去买狗粮了,又可以加餐了,想想就开心呢。

后来小犬把这个在天庭技术论坛发表了一篇帖子来记录了一下这个解决过程,请看下面:

关键代码:

抽象类依赖实现类

总结:

能够解决由于继承造成的类的爆炸问题,扩展起来很灵活,对于两个独立变化的维度,使用桥接模式再适合不过了。
但是桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。