在網上看到一篇很不錯的文章,想轉載下來建立資料庫,共同學習,一起分享。----Noted by me
轉載於:http://chjavach.iteye.com/blog/738056 http://blog.csdn.net/ljianhui
橋接模式(Bridge)
1 場景問題
1.1 發送提示消息
考慮這樣一個實際的業務功能:發送提示消息。基本上所有帶業務流程處理的系統都會有這樣的功能,比如某人有新的工作了,需要發送一條消息提示他。
從業務上看,消息又分成普通消息、加急消息和特急消息多種,不同的消息類型,業務功能處理是不一樣的,比如加急消息是在消息上添加加急,而特急消息除了添加特急外,還會做一條催促的記錄,多久不完成會繼續催促。從發送消息的手段上看,又有系統內短消息、手機短消息、郵件等等。
現在要實現這樣的發送提示消息的功能,該如何實現呢?
1.2 不用模式的解決方案
1:實現簡化版本
先考慮實現一個簡單點的版本,比如:消息先只是實現發送普通消息,發送的方式呢,先實現系統內短消息和郵件。其它的功能,等這個版本完成過後,再繼續添加,這樣先把問題簡單化,實現起來會容易一點。
(1)由於發送普通消息會有兩種不同的實現方式,爲了讓外部能統一操作,因此,把消息設計成接口,然後由兩個不同的實現類,分別實現系統內短消息方式和郵件發送消息的方式。此時系統結構如圖1所示:
圖1 簡化版本的系統結構示意圖
下面看看大致的實現示意。
(2)先來看看消息的統一接口,示例代碼如下:
- /**
- * 消息的統一接口
- */
- public interface Message {
- /**
- * 發送消息
- * @param message 要發送的消息內容
- * @param toUser 消息發送的目的人員
- */
- public void send(String message,String toUser);
- }
(3)再來分別看看兩種實現方式,這裏只是爲了示意,並不會真的去發送Email和站內短消息,先看站內短消息的方式,示例代碼如下:
- /**
- * 以站內短消息的方式發送普通消息
- */
- public class CommonMessageSMS 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:實現發送加急消息
上面的實現,看起來很簡單,對不對。接下來,添加發送加急消息的功能,也有兩種發送的方式,同樣是站內短消息和Email的方式。
加急消息的實現跟普通消息不同,加急消息會自動在消息上添加加急,然後再發送消息;另外加急消息會提供監控的方法,讓客戶端可以隨時通過這個方法來了解對於加急消息處理的進度,比如:相應的人員是否接收到這個信息,相應的工作是否已經開展等等。因此加急消息需要擴展出一個新的接口,除了基本的發送消息的功能,還需要添加監控的功能,這個時候,系統的結構如圖2所示:
圖2 加入發送加急消息後的系統結構示意圖
(1)先看看擴展出來的加急消息的接口,示例代碼如下:
- /**
- * 加急消息的抽象接口
- */
- public interface UrgencyMessage extends Message{
- /**
- * 監控某消息的處理過程
- * @param messageId 被監控的消息的編號
- * @return 包含監控到的數據對象,這裏示意一下,所以用了Object
- */
- public Object watch(String messageId);
- }
(2)相應的實現方式還是發送站內短消息和Email兩種,同樣需要兩個實現類來分別實現這兩種方式,先看站內短消息的方式,示例代碼如下:
- public class UrgencyMessageSMS 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.3 有何問題
上面這樣實現,好像也能滿足基本的功能要求,可是這麼實現好不好呢?有沒有什麼問題呢?
咱們繼續向下來添加功能實現,爲了簡潔,就不再去進行代碼示意了,通過實現的結構示意圖就可以看出實現上的問題。
1:繼續添加特急消息的處理
特急消息不需要查看處理進程,只要沒有完成,就直接催促,也就是說,對於特急消息,在普通消息的處理基礎上,需要添加催促的功能。而特急消息、還有催促的發送方式,相應的實現方式還是發送站內短消息和Email兩種,此時系統的結構如圖3所示:
圖3 加入發送特急消息後的系統結構示意圖
仔細觀察上面的系統結構示意圖,會發現一個很明顯的問題,那就是:通過這種繼承的方式來擴展消息處理,會非常不方便。
你看,實現加急消息處理的時候,必須實現站內短消息和Email兩種處理方式,因爲業務處理可能不同;在實現特急消息處理的時候,又必須實現站內短消息和Email這兩種處理方式。
這意味着,以後每次擴展一下消息處理,都必須要實現這兩種處理方式,是不是很痛苦,這還不算完,如果要添加新的實現方式呢?繼續向下看吧。
2:繼續添加發送手機消息的處理方式
如果看到上面的實現,你還感覺問題不是很大的話,繼續完成功能,添加發送手機消息的處理方式。
仔細觀察現在的實現,如果要添加一種新的發送消息的方式,是需要在每一種抽象的具體實現裏面,都要添加發送手機消息的處理的。也就是說:發送普通消息、加急消息和特急消息的處理,都可以通過手機來發送。這就意味着,需要添加三個實現。此時系統結構如圖4所示:
圖4 加入發送手機消息後的系統結構示意圖
這下能體會到這種實現方式的大問題了吧。
3:小結一下出現的問題
採用通過繼承來擴展的實現方式,有個明顯的缺點:擴展消息的種類不太容易,不同種類的消息具有不同的業務,也就是有不同的實現,在這種情況下,每個種類的消息,需要實現所有不同的消息發送方式。
更可怕的是,如果要新加入一種消息的發送方式,那麼會要求所有的消息種類,都要加入這種新的發送方式的實現。
要是考慮業務功能上再擴展一下呢?比如:要求實現羣發消息,也就是一次可以發送多條消息,這就意味着很多地方都得修改,太恐怖了。
那麼究竟該如何實現才能既實現功能,又能靈活的擴展呢?
========待續見2========