一、概述
一般問題:一個類需要在兩個以上維度擴展,采用繼承方式會導致子類數量過多
核心方案:將抽象部分與實現部分分離,使其都可以獨立變化
設計意圖:橋接模式不是將兩個不相干的類鏈接,而是將一個需要多維度變化的類拆分成抽象部分和實現部分,並且在抽象層對兩者做組合關聯,是用組合的方式來解決繼承的問題。舉個例子,如果一個類在兩個維度分別有m和n種變化,采用繼承的方式就需要擴展出m*n個子類,且一個維度每增加一種變化就多出另一個維度變化總數的子類;如果將兩個維度拆分再組合,加起來也只有m+n個子類,且每個維度獨立擴展,一個維度增加一種變化只需要增加1個子類。
如上圖,Abstraction就是橋接模式中的“橋”,它含有一個實現部分實例,且提供動態設置具體實現類地方法,這樣抽象部分和實現部分的子類可以隨意組合。
下面舉一個簡單的例子:夏天都喜歡吃燒烤,就以燒烤為例,我們從兩個維度分析:從食材上有雞翅、雞腿等;從風味上有微辣、特辣等。
我們把食材做為抽象部分,把風味作為實現部分:
先看實現部分變化:
風味類Spicy
public interface Spicy{ String taste(); }
微辣SlightSpicy
public class SlightSpicy implements Spicy{ public String taste(){ return "微辣"; }
}
特辣ExtraSpicy
public class ExtraSpicy implements Spicy{ public String taste(){ return "特辣"; } }
再看抽象部分變化:
燒烤類Barbecue
public abstract class Barbecue{ protected Spicy mSpicy; //實現部分實例 public Barbecue(Spicy spicy){ 橋接模式的關鍵,組合實現和抽象 this.mSpicy= spicy; } public abstract void eat(); }
雞翅類ChickenWing
public class ChickenWing extends Barbecue{ public ChickenWing (Spicy spicy){ super(spicy); } public void eat(){ System.out.println( "雞翅:"+super.mSpicy.taste()); } }
測試:
public class Test{ public static void main(String[] args){ Barbecue barbecue = new ChickenWing(new SlightSpicy()); barbecue .eat(); Barbecue barbecue2 = new ChickenWing(new ExtraSpicy()); barbecue2 .eat(); } }
輸出:
雞翅:微辣
雞翅:特辣
二、實戰應用
我們知道Android中ListView的Adapter的設計用到了適配器模式,實際上Adapter本身還包含在一個橋接模式之中!
上圖是整個AdapterView類圖,對比橋接模式的UML圖,不難看出整體上它是個大的橋接模式,我們抽取其中的AbsListView這個小的橋接模式來分析:
AbsListView表示集合視圖,其有兩個維度變化:
- 顯示形式變化,如列表形式ListView或網格形式GridView;
- 數據類型變化,如字符串數組SimpleAdapter或數據庫游標CursorAdapter
Android將顯示形式作為抽象部分,數據類型作為實現部分,兩個部分各自獨立變化。
抽象部分和實現部分在AbsListView抽象層做了組合關聯,體現代碼如下:
public abstract class AbsListView extends AdapterView<ListAdapter>{ ListAdapter mAdapter; @Override public void setAdapter(ListAdapter adapter) { if (adapter != null) { mAdapterHasStableIds = mAdapter.hasStableIds(); if (mChoiceMode != CHOICE_MODE_NONE && mAdapterHasStableIds && mCheckedIdStates == null) { mCheckedIdStates = new LongSparseArray<Integer>(); } } clearChoices(); } }
三、總結
總結:橋接模式是一種結構型設計模式,根據最小繼承原則,將各個變化部分分離,從而實現獨立變化互不干涉,但又在更高的抽象層實現組合以保證各子類能動態結合。
用一句話來概括橋接模式:
“打斷骨頭還連着筋”
優點:
- 抽象和實現分離
- 易於擴展
缺點:橋接模式的引入會增加系統的理解與設計難度,由於聚合關聯關系建立在抽象層,要求開發者針對抽象進行設計與編程。