橋接模式(Bridge),將抽象部分與它的實現部分分離,使它們均可以獨立地變化。(實現系統可能有多角度分類,每一種分類都有可能變化(只用繼承會形成類的大量增長,不能知足開放——封閉原則),那麼就把這種多角度分離出來讓它們獨立變化,減小它們之間的耦合)java
抽象與它的實現分離,並非說讓抽象類與其派生類分離,實現指的是抽象類和它的派生類用來實現本身的對象。例:手機既能夠按照品牌來分類,也能夠按照功能來分類,具體能夠參考下面實例:c#
按品牌分類:ide
按軟件實現分類:this
因爲實現的方式有多種,橋接模式的核心意圖就是把這些實現獨立出來,讓他們各自地變化,這就使得每種實現的變化不會影響其餘實現,從而達到應對變化的目的。code
橋接模式實現:對象
這樣就解決了按品牌分類或按軟件分類增長新品牌/軟件時的複雜性和代碼不可複用性。繼承
橋接模式UML結構圖:接口
例(手機軟件):遊戲
//手機品牌 abstract class HandsetBrand { protected HandsetSoft soft; //設置手機軟件 public void SetHandsetSoft(HandsetSoft soft) { this.soft = soft; } //運行 public abstract void Run(); } //手機品牌N class HandsetBrandN : HandsetBrand { public override void Run() { soft.Run(); } } //手機品牌M class HandsetBrandM : HandsetBrand { public override void Run() { soft.Run(); } } //手機品牌S class HandsetBrandS : HandsetBrand { public override void Run() { soft.Run(); } } //手機軟件 abstract class HandsetSoft { public abstract void Run(); } //手機遊戲 class HandsetGame : HandsetSoft { public override void Run() { Console.WriteLine("運行手機遊戲"); } } //手機通信錄 class HandsetAddressList : HandsetSoft { public override void Run() { Console.WriteLine("運行手機通信錄"); } } //手機MP3播放 class HandsetMP3 : HandsetSoft { public override void Run() { Console.WriteLine("運行手機MP3播放"); } } class Program { static void Main(string[] args) { HandsetBrand ab; ab = new HandsetBrandN(); ab.SetHandsetSoft(new HandsetGame()); ab.Run(); ab.SetHandsetSoft(new HandsetAddressList()); ab.Run(); ab = new HandsetBrandM(); ab.SetHandsetSoft(new HandsetGame()); ab.Run(); ab.SetHandsetSoft(new HandsetAddressList()); ab.Run(); Console.Read(); } }
例(發送提示消息):ci
消息分紅普通消息、加急消息和特急消息多種,不一樣的消息類型,業務功能處理是不同的,好比加急消息是在消息上添加加急,而特急消息除了添加特急外,還會作一條催促的記錄,多久不完成會繼續催促。從發送消息的手段上看,又有系統內短消息、手機短消息、郵件等等。
所有采用繼承,不使用橋接模式的UML圖(若是繼續擴展消息類型或者發送方式將會十分繁瑣):
例:繼續添加發送手機消息的處理方式(這個時候代碼結構就逐漸開始變得複雜):
橋接模式實現:
代碼:
public interface MessageImplementor { public void send(String message,String toUser); } public class MessageEmail implements MessageImplementor { public void send(String message, String toUser) { System.out.println("使用Email的方式,發送消息'" + message + "'給" + toUser); } } public class MessageMobile implements MessageImplementor { public void send(String message, String toUser) { System.out.println("使用手機短消息的方式,發送消息'" + message + "'給" + toUser); } } public class MessageSMS implements MessageImplementor { public void send(String message, String toUser) { System.out.println("使用站內短消息的方式,發送消息'" + message + "'給" + toUser); } } public abstract class AbstractMessage { protected MessageImplementor impl; public AbstractMessage(MessageImplementor impl) { this.impl = impl; } public void sendMessage(String message, String toUser) { this.impl.send(message, toUser); } } public class CommonMessage extends AbstractMessage { public CommonMessage(MessageImplementor impl) { super(impl); } public void sendMessage(String message, String toUser) { super.sendMessage(message, toUser); } } public class UrgencyMessage extends AbstractMessage { public UrgencyMessage(MessageImplementor impl) { super(impl); } public void sendMessage(String message, String toUser) { message = "加急:" + message; super.sendMessage(message, toUser); } public Object watch(String messageId) { return null; } } public class SpecialUrgencyMessage extends AbstractMessage { public SpecialUrgencyMessage(MessageImplementor impl) { super(impl); } public void hurry(String messageId) { // 執行催促的業務,發出催促的信息 } public void sendMessage(String message, String toUser) { message = "特急:" + message; super.sendMessage(message, toUser); } } /* * 意圖:將抽象部分與實現部分分離,使它們均可以獨立的變化。 * 主要解決:在有多種可能會變化的狀況下,用繼承會形成類爆炸問題,擴展起來不靈活。 * 什麼時候使用:實現系統可能有多個角度分類,每一種角度均可能變化。 * 如何解決:把這種多角度分類分離出來,讓它們獨立變化,減小它們之間耦合。 * 關鍵代碼:抽象類依賴實現類。 */ /* * 該發送消息的實例因爲發送方式的可擴展性和發送級別(普通,加急,特急等)的可擴展性,使用繼承並不靈活 * 考慮使用橋接模式:分離這兩部分,使它們獨立變化,減小它們之間的耦合(低耦合) * 注意事項:有時候咱們看待問題的角度不一樣,可能採起的分離措施也會有所不一樣,所以代碼結構也會有所不一樣 *(這種過於複雜的狀況下橋接模式就再也不能說很合適,由於橋接模式自己就加重了代碼的複雜性,較於繼承更加難以理解一些,可是使用得當則會讓代碼結構更加簡潔清晰) */ public class Client { public static void main(String[] args) { MessageImplementor impl = new MessageSMS(); //接口下的發送方式定義 AbstractMessage m = new CommonMessage(impl); //發送消息的方式實現 m.sendMessage("請喝一杯茶", "小李"); m = new UrgencyMessage(impl); m.sendMessage("請喝一杯茶", "小李"); m = new SpecialUrgencyMessage(impl); m.sendMessage("請喝一杯茶", "小李"); impl = new MessageMobile(); m = new CommonMessage(impl); m.sendMessage("請喝一杯茶", "小李"); m = new UrgencyMessage(impl); m.sendMessage("請喝一杯茶", "小李"); m = new SpecialUrgencyMessage(impl); m.sendMessage("請喝一杯茶", "小李"); impl = new MessageEmail(); m = new CommonMessage(impl); m.sendMessage("請喝一杯茶", "小李"); m = new UrgencyMessage(impl); m.sendMessage("請喝一杯茶", "小李"); m = new SpecialUrgencyMessage(impl); m.sendMessage("請喝一杯茶", "小李"); } }