聲明:轉載請說明來源:http://www.cnblogs.com/pony1223/p/7530721.html
一、引出橋接模式
假設我們現在有一個項目,這個項目列就是我們是生產遙控器的廠商,承接各種遙控器的生產,比如我們現在承接的有LG、索尼的電視廠商的,那如果我們現在要設計的話,我們首先想到的最簡單的方式就是如下的方式:
對上述類圖作下解釋:各大電視機廠商對外提供的一般都是統一接口,以便大家直接操作電視的時候,也就是我們通常如果遙控器丟失的時候,可以直接去按電視機下面的按鈕進行直接操作,基本都是一樣的,就是因為實現了統一的接口,但因為各自的采用的協議或者算法的不同,因此實現類是不一樣的,那么這個時候對於遙控器生產廠商而言要做的,首先要對外是一致的,這樣方便操作,但同時又需要去調用各大電視機廠商的實現類,那么最容易的就是繼承各個實現類,同時實現自己的接口去做了,於是代碼產生如下:
1.電視機廠商的接口:
public interface Control { public void On(); public void Off(); public void setChannel(int ch); public void setVolume(int vol); }
2.LG 索尼公司自己的實現類
package study.designmode.bridgemode.control; public class LGControl implements Control { @Override public void On() { // TODO Auto-generated method stub System.out.println("**Open LG TV**"); } @Override public void Off() { // TODO Auto-generated method stub System.out.println("**Off LG TV**"); } @Override public void setChannel(int ch) { // TODO Auto-generated method stub System.out.println("**The LG TV Channel is setted "+ch+"**"); } @Override public void setVolume(int vol) { // TODO Auto-generated method stub System.out.println("**The LG TV Volume is setted "+vol+"**"); } } package study.designmode.bridgemode.control; public class SonyControl implements Control { @Override public void On() { // TODO Auto-generated method stub System.out.println("*Open Sony TV*"); } @Override public void Off() { // TODO Auto-generated method stub System.out.println("*Off Sony TV*"); } @Override public void setChannel(int ch) { // TODO Auto-generated method stub System.out.println("*The Sony TV Channel is setted "+ch+"*"); } @Override public void setVolume(int vol) { // TODO Auto-generated method stub System.out.println("*The Sony TV Volume is setted "+vol+"*"); } }
3.遙控器廠商的接口
package study.designmode.bridgemode; public interface TvControl { public void Onoff(); public void nextChannel(); public void preChannel(); }
4.實現類:
package study.designmode.bridgemode; import study.designmode.bridgemode.control.LGControl; public class LGTvControl extends LGControl implements TvControl{ private static int ch=0; private static boolean ison=false; public void Onoff() { if(ison) { ison=false; super.Off(); }else{ ison=true; super.On(); } } public void nextChannel() { ch++; super.setChannel(ch); } public void preChannel() { ch--; if(ch<0) { ch=200; } super.setChannel(ch); } }
package study.designmode.bridgemode; import study.designmode.bridgemode.control.SonyControl; public class SonyTvControl extends SonyControl implements TvControl{ private static int ch=0; private static boolean ison=false; public void Onoff() { if(ison) { ison=false; super.Off(); }else{ ison=true; super.On(); } } public void nextChannel() { ch++; super.setChannel(ch); } public void preChannel() { ch--; if(ch<0) { ch=200; } super.setChannel(ch); } }
5.測試:
package study.designmode.bridgemode; public class MainTest { public static void main(String[] args) { LGTvControl mLGTvControl=new LGTvControl(); SonyTvControl mSonyTvControl=new SonyTvControl(); mLGTvControl.Onoff(); mLGTvControl.nextChannel(); mLGTvControl.nextChannel(); mLGTvControl.preChannel(); mLGTvControl.Onoff(); mSonyTvControl.Onoff(); mSonyTvControl.preChannel(); mSonyTvControl.preChannel(); mSonyTvControl.preChannel(); mSonyTvControl.Onoff(); } }
結果:
思考帶來的問題:如果我現在要新增承接一個電視廠商夏普的,那么這個時候我需要再實現一個類,然后繼承自夏普的實現類,那么帶來的問題就是每增加一個電視機廠商的活,那么遙控器廠商就生成一個遙控器的實現類,如果遙控器想要對外界的接口發生以下變化,那么所有的實現類也要變化;也就是遙控器廠商和電視機廠商之間是緊密關聯在一起的,沒法獨立開來,你電視器廠商增加一個,我就要增加一個;拿就是一種N*N的關系,有沒有辦法做到1*N;就是你電視器廠商的變化,我遙控器廠商不去變化,但可以滿足要求,統一一個來實現呢?拿就是橋接模式了。
二、解決辦法
要解決上面的問題,首先我們需要分析變化和不變化的部分,上面的需求可以看出,變化的應該是電視機廠商部分,但電視廠商已經統一化了,那么根據以往的經驗我們要少用繼承,多用組合,如果我們采用組合方式來解決呢,類圖如下:
從上述可以看出,滿足了我們的1*n的想法,這也橋接模式的意義所在。
橋接模式:將實現與抽象放在兩個不同的類層次中,使兩個層次可以獨立改變。(這里的抽象就是我們遙控器廠商,實現就是我們的電視機廠商)
代碼實現如下:
1.抽象類
package study.designmode.bridgemode.bridge; import study.designmode.bridgemode.control.Control; public abstract class TvControlabs { Control mControl=null; public TvControlabs(Control mControl) { this.mControl=mControl; } public abstract void Onoff(); public abstract void nextChannel(); public abstract void preChannel(); }
2.實現類:
package study.designmode.bridgemode.bridge; import study.designmode.bridgemode.control.Control; public class TvControl extends TvControlabs { private int ch=0; private boolean ison=false; public TvControl(Control mControl) { super(mControl); } @Override public void Onoff() { // TODO Auto-generated method stub if(ison) { ison=false; mControl.Off(); }else{ ison=true; mControl.On(); } } @Override public void nextChannel() { // TODO Auto-generated method stub ch++; mControl.setChannel(ch); } @Override public void preChannel() { // TODO Auto-generated method stub ch--; if(ch<0) { ch=200; } mControl.setChannel(ch); } }
3.測試:
package study.designmode.bridgemode.bridge; import study.designmode.bridgemode.control.LGControl; import study.designmode.bridgemode.control.SharpControl; import study.designmode.bridgemode.control.SonyControl; public class MainTest { public static void main(String[] args) { TvControl mLGTvControl; TvControl mSonyTvControl; mSonyTvControl=new TvControl(new SonyControl()); mLGTvControl=new TvControl(new LGControl()); mLGTvControl.Onoff(); mLGTvControl.nextChannel(); mLGTvControl.nextChannel(); mLGTvControl.preChannel(); mLGTvControl.Onoff(); mSonyTvControl.Onoff(); mSonyTvControl.preChannel(); mSonyTvControl.preChannel(); mSonyTvControl.preChannel(); mSonyTvControl.Onoff(); /* newTvControl mSharpTvControl; mSharpTvControl=new newTvControl(new SharpControl()); mSharpTvControl.Onoff(); mSharpTvControl.nextChannel(); mSharpTvControl.setChannel(9); mSharpTvControl.setChannel(28); mSharpTvControl.Back(); mSharpTvControl.Onoff();*/ } }
三、總結
當系統有多維度角度分類的時候,而每一種分類又有可能的變化,考慮使用橋接模式。橋接的目的是分離抽象與實現,使抽象和實現可以獨立變化。
和策略模式的差異:
橋接的目的是讓底層實現和上層接口可以分別演化,從而提高移植性
策略的目的是將復雜的算法封裝起來,從而便於替換不同的算法。
橋接是往往是為了利用已有的方法或類
策略是為了擴展和修改,並提供動態配置
橋接強調接口對象僅僅提供基本的操作
策略強調接口對象提供的是這一種算法