在學(xué)習(xí)這個(gè)設(shè)計(jì)模式的時(shí)候儡嘶,我是比較痛苦的瞒爬。因?yàn)榫W(wǎng)上的很多教程雖然主題是橋(Bridge),但是一直在說如何拆分卑惜,如何解耦瘾带。直到我真正理解橋接模式之后妒蔚,才發(fā)現(xiàn)那些教程都背離了這一設(shè)計(jì)模式的名字---Bridge,即一個(gè)起到連接作用的物體月弛。
橋接的是什么肴盏?
試想有這樣一個(gè)類層次結(jié)構(gòu),它實(shí)現(xiàn)的是類的意義層面上的抽象:
另外還有一個(gè)接口層次結(jié)構(gòu)帽衙,而它表示的則是從類的行為層面進(jìn)行抽象:
為了讓兩者能夠松耦合地運(yùn)行在一起菜皂,通過在Shape中添加DrawingProgramming的實(shí)例的方式進(jìn)行聚合,即實(shí)現(xiàn)了橋接模式:
橋接模式
一般來說厉萝,橋接模式可以概括為下圖:
可以看到圖中共有5個(gè)主要的概念:
- Client: 客戶端恍飘,對類進(jìn)行調(diào)用;
- Abstraction:抽象類谴垫,從類的實(shí)際含義角度出發(fā)章母,對其進(jìn)行抽象,并包含一個(gè)Implementor的實(shí)例
- Implementor:實(shí)現(xiàn)者翩剪,一般是一個(gè)定義了類的各種行為的接口乳怎;
- RefinedAbstraction:細(xì)化類,擴(kuò)展(extends)了Abstraction前弯,從類的含義上進(jìn)行結(jié)構(gòu)的堆疊蚪缀;
- ConcreteImplementor A&B:具體實(shí)現(xiàn),即實(shí)現(xiàn)了Implementor中定義的方法恕出,提供類的行為的具體內(nèi)容询枚。
其實(shí)看到這個(gè)圖之后,有的人可能會提出異議:
為什么不直接將Implementor中定義的方法放入Abstraction浙巫,然后讓RefinedAbstraction直接實(shí)現(xiàn)呢金蜀?
單一責(zé)任原則
單一責(zé)任原則(SRP:Single responsibility principle)又稱單一職責(zé)原則刷后,如果一個(gè)類承擔(dān)的責(zé)任過多,就等于把這些責(zé)任耦合在一起了渊抄。一個(gè)責(zé)任的變化可能會影響這個(gè)類完成其他責(zé)任的能力惠险。這種耦合會導(dǎo)致脆弱的設(shè)計(jì),當(dāng)發(fā)生變更時(shí)抒线,設(shè)計(jì)會遭受到意想不到的破壞班巩。
SRP正是橋接模式要維護(hù)的原則。試問如果真的將方法放入Abstraction后嘶炭,它的子類將會為了實(shí)現(xiàn)放入父類的方法而絞盡腦汁抱慌,盡管很可能某個(gè)方法和某個(gè)子類沒有任何關(guān)系;而如果不把大部分子類的行為方法抽象到父類中眨猎,又會導(dǎo)致類型之間的不兼容抑进,引發(fā)了大量的instanceof海洋(instance of ocean)。
橋接模式的優(yōu)點(diǎn)
使用橋接模式睡陪,主要是看中了它所帶來的優(yōu)點(diǎn):
- 將類的含義層次和行為層次松耦合寺渗;
- 使整套API能夠擁有兩個(gè)維度的擴(kuò)展鏈,提到了系統(tǒng)的獨(dú)立性兰迫;
- 隱藏了更多的細(xì)節(jié)信殊;
- 使用設(shè)計(jì)模式能夠使其他開發(fā)維護(hù)者更容易理解。
使用范例
從下圖中我們可以看出汁果,Shape和DrawAPI很好地解耦了涡拘,Circle從類的含義出發(fā)進(jìn)行了擴(kuò)展,而RedCircle和GreenCircle從類的行為出發(fā)進(jìn)行了接口的實(shí)現(xiàn)据德,兩者互不影響鳄乏,且通過一個(gè)聚合的關(guān)系,將兩個(gè)維度松耦合到了一起棘利。