Java設計模式9:橋接模式
一、橋接模式:
橋接模式是用於把抽象化與實現化解耦,使得二者可以獨立變化。這種型別的設計模式屬於結構型模式,它通過提供抽象化和實現化之間的橋接結構,來實現二者的解耦。
二、示例程式碼:
先來考慮下如下場景:
傳送訊息功能。基本上所有帶業務流程處理的系統都會有這樣的功能,比如OA上有尚未處理完畢的檔案,需要傳送一條訊息提示他。從業務上看,訊息又分為普通訊息、加急訊息多種,不同的訊息型別,業務功能處理是不一樣的,比如加急訊息是在訊息上新增加急。從傳送訊息的方式上看,又有系統內訊息、手機訊息、郵件等。
先來看下不使用設計模式情況下實現如上功能,直接上程式碼:
先建立統一訊息介面
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 14:58
* @desc : 訊息的統一介面
* @version: 1.0
* </pre>
*/
public interface Message {
void send (String message,String toName);
}
系統方式傳送普通訊息的實現類:
/** * <pre> * @author : orange * @e-mail :
[email protected] * @time : 2018/10/12 15:02 * @desc : 系統內普通訊息 * @version: 1.0 * </pre> */ public class CommonMessageSMS implements Message { @Override public void send(String message, String toName) { System.out.println(String.format("使用系統傳送訊息方式,傳送訊息 %s 給 %s",message,toName)); } }
郵件方式傳送普通訊息的實現類:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:05
* @desc : 使用郵件的方式傳送普通訊息
* @version: 1.0
* </pre>
*/
public class CommonMessageEmail implements Message {
@Override
public void send(String message, String toName) {
System.out.println(String.format("使用郵件傳送普通訊息方式,傳送訊息 %s 給 %s",message,toName));
}
}
那麼這個時候我們需要實現加急訊息的功能,同樣有系統和郵件兩種訊息方式。
我們為了簡化業務,加急訊息是在普通訊息內容前加上“加急”字串。
系統方式傳送加急訊息:
**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:10
* @desc : 系統內加急訊息實現類
* @version: 1.0
* </pre>
*/
public class UrgentMessageSMS implements Message {
@Override
public void send(String message, String toName) {
message = "加急" + message;
System.out.println(String.format("使用系統內傳送訊息方式,放送訊息 %s 給 %s",message,toName));
}
}
郵件方式傳送加急訊息:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:13
* @desc : 使用郵件方式傳送加急訊息
* @version: 1.0
* </pre>
*/
public class UrgentMessageEmail implements Message {
@Override
public void send(String message, String toName) {
message = "加急" + message;
System.out.println(String.format("使用郵件傳送訊息方式,傳送內容", message, toName));
}
}
觀察上面實現訊息功能的程式碼,用這種直接實現介面的方式來拓展訊息處理,會非常不方便。實現加急訊息處理的時候,必須實現系統內訊息和郵件兩種處理方式。如果我們又必須要來再實現第三種訊息型別:特急訊息傳送,又必須實現系統內訊息和郵件兩種處理方式。這意味著,以後每次拓展一次訊息型別,都必須要實現這兩種訊息處理方式,這還不算完,如果要新增新的處理方式呢?如果手機發送的方式?那麼我們就必須增加普通,加急,特急三種實現類。在這種情況下,每一種類的訊息,需要實現所有不同的訊息傳送方式。更可怕的是,如果要新加入一種訊息的傳送方式,那麼會要求所有的訊息種類都有加入這種新的傳送方式的實現。
三、使用橋樑模式來解決問題
首先同樣的統一訊息請求介面:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 14:58
* @desc : 訊息的統一介面
* @version: 1.0
* </pre>
*/
public interface Message {
void send (String message,String toName);
}
抽象訊息型別類:
**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:40
* @desc : 抽象訊息類
* @version: 1.0
* </pre>
*/
public abstract class AbstractMessage{
private Message message;
public AbstractMessage(Message message){
this.message = message;
}
public void sendMessage (String message,String toName){
this.message.send(message,toName);
}
}
普通訊息實現類:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:47
* @desc : 普通訊息實現類
* @version: 1.0
* </pre>
*/
public class CommonMessage extends AbstractMessage{
public CommonMessage(Message message){
super(message);
}
@Override
public void sendMessage(String message, String toName) {
super.sendMessage(message,toName);
}
}
加急訊息實現類:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:53
* @desc : 加急訊息實現類
* @version: 1.0
* </pre>
*/
public class UrgencyMessage extends AbstractMessage {
public UrgencyMessage(Message message) {
super(message);
}
@Override
public void sendMessage(String message, String toName) {
message = "加急" + message;
super.sendMessage(message,toName);
}
}
系統訊息:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:02
* @desc : 使用系統方式傳送訊息
* @version: 1.0
* </pre>
*/
public class MessageSMS implements Message {
@Override
public void send(String message, String toName) {
System.out.println(String.format("使用系統傳送訊息方式,傳送訊息 %s 給 %s",message,toName));
}
}
郵件訊息:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:05
* @desc : 使用郵件的方式傳送訊息
* @version: 1.0
* </pre>
*/
public class MessageEmail implements Message {
@Override
public void send(String message, String toName) {
System.out.println(String.format("使用郵件傳送訊息方式,傳送訊息 %s 給 %s",message,toName));
}
}
客戶端測試:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/10/12 15:57
* @desc :
* @version: 1.0
* </pre>
*/
public class Client {
public static void main(String[] args) {
Message message = new MessageSMS();
AbstractMessage abstractMessage = new CommonMessage(message);
abstractMessage.sendMessage("呵呵呵", "老闆");
message = new MessageEmail();
abstractMessage = new UrgencyMessage(message);
abstractMessage.sendMessage("嘿嘿嘿","女朋友");
}
}
四、總結:
個人理解:橋接是一個介面,它與一方應該是繫結的,也就是解耦的雙方中的一方必然是繼承這個介面的,這一方就是實現方,而另一方正是要與這一方解耦的抽象方,如果不採用橋接模式,一般我們的處理方式是直接使用繼承來實現,這樣雙方之間處於強連結,類之間關聯性極強,如要進行擴充套件,必然導致類結構急劇膨脹。採用橋接模式,正是為了避免這一情況的發生,將一方與橋繫結,即實現橋介面,另一方在抽象類中呼叫橋介面(指向的實現類),這樣橋方可以通過實現橋介面進行單方面擴充套件,而另一方可以繼承抽象類而單方面擴充套件,而之間的呼叫就從橋介面來作為突破口,不會受到雙方擴充套件的任何影響。