來寫一個你們既陌生又熟悉的設計模式,也是很是實用的一個設計模式,那就是橋接模式。html
說陌生是不少朋友並不熟悉這個設計模式,說熟悉是不少人常常見到或者是下意識的用到這個設計模式,只是不知道罷了。橋接模式是很是實用的一個模式,下面就來寫寫它。java
考慮這樣一個實際的業務功能:發送提示消息。基本上全部帶業務流程處理的系統都會有這樣的功能,好比某人有新的工做了,須要發送一條消息提示他。
從業務上看,消息又分紅普通消息、加急消息和特急消息多種,不一樣的消息類型,業務功能處理是不同的,好比加急消息是在消息上添加加急,而特急消息除了添加特急外,還會作一條催促的記錄,多久不完成會繼續催促。從發送消息的手段上看,又有系統內短消息、手機短消息、郵件等等。
如今要實現這樣的發送提示消息的功能,該如何實現呢?設計模式
1:實現簡化版本
先考慮實現一個簡單點的版本,好比:消息先只是實現發送普通消息,發送的方式呢,先實現系統內短消息和郵件。其它的功能,等這個版本完成事後,再繼續添加,這樣先把問題簡單化,實現起來會容易一點。
(1)因爲發送普通消息會有兩種不一樣的實現方式,爲了讓外部能統一操做,所以,把消息設計成接口,而後由兩個不一樣的實現類,分別實現系統內短消息方式和郵件發送消息的方式。此時系統結構如圖1所示:學習
圖1 簡化版本的系統結構示意圖spa
下面看看大體的實現示意。設計
(2)先來看看消息的統一接口,示例代碼以下:code
/** * 消息的統一接口 */ public interface Message { /** * 發送消息 * @param message 要發送的消息內容 * @param toUser 消息發送的目的人員 */ public void send(String message,String toUser); }
(3)再來分別看看兩種實現方式,這裏只是爲了示意,並不會真的去發送Email和站內短消息,先看站內短消息的方式,示例代碼以下:htm
/** * 以站內短消息的方式發送普通消息 */ public class CommonMessageS MS implements Message{ public void send(String message, String toUser) { System.out.println("使用站內短消息的方式,發送消息'" +message+"'給"+toUser); } }
一樣的,實現以Email的方式發送普通消息,示例代碼以下:對象
/** * 以Email的方式發送普通消息 */ public class CommonMessageEmail implements Message{ public void send(String message, String toUser) { System.out.println("使用Email的方式,發送消息'" +message+"'給"+toUser); } }
2:實現發送加急消息blog
上面的實現,看起來很簡單,對不對。接下來,添加發送加急消息的功能,也有兩種發送的方式,一樣是站內短消息和Email的方式。
加急消息的實現跟普通消息不一樣,加急消息會自動在消息上添加加急,而後再發送消息;另外加急消息會提供監控的方法,讓客戶端能夠隨時經過這個方法來了解對於加急消息處理的進度,好比:相應的人員是否接收到這個信息,相應的工做是否已經開展等等。所以加急消息須要擴展出一個新的接口,除了基本的發送消息的功能,還須要添加監控的功能,這個時候,系統的結構如圖2所示:
圖2 加入發送加急消息後的系統結構示意圖
(1)先看看擴展出來的加急消息的接口,示例代碼以下:
/** * 加急消息的抽象接口 */ public interface UrgencyMessage extends Message{ /** * 監控某消息的處理過程 * @param messageId 被監控的消息的編號 * @return 包含監控到的數據對象,這裏示意一下,因此用了Object */ public Object watch(String messageId); }
(2)相應的實現方式仍是發送站內短消息和Email兩種,一樣須要兩個實現類來分別實現這兩種方式,先看站內短消息的方式,示例代碼以下:
public class UrgencyMessageS MS implements UrgencyMessage{ public void send(String message, String toUser) { message = "加急:"+message; System.out.println("使用站內短消息的方式,發送消息'" +message+"'給"+toUser); } public Object watch(String messageId) { //獲取相應的數據,組織成監控的數據對象,而後返回 return null; } }
再看看Emai的方式,示例代碼以下:
public class UrgencyMessageEmail implements UrgencyMessage{ public void send(String message, String toUser) { message = "加急:"+message; System.out.println("使用Email的方式,發送消息'" +message+"'給"+toUser); } public Object watch(String messageId) { //獲取相應的數據,組織成監控的數據對象,而後返回 return null; } }
(3)事實上,在實現加急消息發送的功能上,可能會使用前面發送不一樣消息的功能,也就是讓實現加急消息處理的對象繼承普通消息的相應實現,這裏爲了讓結構簡單一點,清晰一點,因此沒有這樣作。
上面這樣實現,好像也能知足基本的功能要求,但是這麼實現好很差呢?有沒有什麼問題呢?
我們繼續向下來添加功能實現,爲了簡潔,就再也不去進行代碼示意了,經過實現的結構示意圖就能夠看出實現上的問題。
1:繼續添加特急消息的處理
特急消息不須要查看處理進程,只要沒有完成,就直接催促,也就是說,對於特急消息,在普通消息的處理基礎上,須要添加催促的功能。而特急消息、還有催促的發送方式,相應的實現方式仍是發送站內短消息和Email兩種,此時系統的結構如圖3所示:
圖3 加入發送特急消息後的系統結構示意圖
仔細觀察上面的系統結構示意圖,會發現一個很明顯的問題,那就是:經過這種繼承的方式來擴展消息處理,會很是不方便。
你看,實現加急消息處理的時候,必須實現站內短消息和Email兩種處理方式,由於業務處理可能不一樣;在實現特急消息處理的時候,又必須實現站內短消息和Email這兩種處理方式。
這意味着,之後每次擴展一下消息處理,都必需要實現這兩種處理方式,是否是很痛苦,這還不算完,若是要添加新的實現方式呢?繼續向下看吧。
2:繼續添加發送手機消息的處理方式
若是看到上面的實現,你還感受問題不是很大的話,繼續完成功能,添加發送手機消息的處理方式。
仔細觀察如今的實現,若是要添加一種新的發送消息的方式,是須要在每一種抽象的具體實現裏面,都要添加發送手機消息的處理的。也就是說:發送普通消息、加急消息和特急消息的處理,均可以經過手機來發送。這就意味着,須要添加三個實現。此時系統結構如圖4所示:
圖4 加入發送手機消息後的系統結構示意圖
這下能體會到這種實現方式的大問題了吧。
3:小結一下出現的問題
採用經過繼承來擴展的實現方式,有個明顯的缺點:擴展消息的種類不太容易,不一樣種類的消息具備不一樣的業務,也就是有不一樣的實現,在這種狀況下,每一個種類的消息,須要實現全部不一樣的消息發送方式。
更可怕的是,若是要新加入一種消息的發送方式,那麼會要求全部的消息種類,都要加入這種新的發送方式的實現。
要是考慮業務功能上再擴展一下呢?好比:要求實現羣發消息,也就是一次能夠發送多條消息,這就意味着不少地方都得修改,太恐怖了。
那麼究竟該如何實現才能既實現功能,又能靈活的擴展呢?
《研磨設計模式》一書已經上市,卓越網銷售連接:
http://www.amazon.cn/%E7%A0%94%E7%A3%A8%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E9%99%88%E8%87%A3/dp/B004G8P90S/ref=sr_1_1?ie=UTF8&qid=1295358211&sr=8-1
也能夠直接在卓越網上搜索《研磨設計模式》
噹噹網的銷售連接:http://product.dangdang.com/product.aspx?product_id=20994349&ref=search-0-mix
========未完待續
---------------------------------------------------------------------------
私塾在線學習網原創內容 跟着cc學設計系列 之 研磨設計模式
原創內容,轉載請註明出處【http://sishuok.com/forum/blogPost/list/106.html】
---------------------------------------------------------------------------