1. 程式人生 > >Java設計模式9:橋接模式

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("嘿嘿嘿","女朋友");

    }
}

 

四、總結:

個人理解:橋接是一個介面,它與一方應該是繫結的,也就是解耦的雙方中的一方必然是繼承這個介面的,這一方就是實現方,而另一方正是要與這一方解耦的抽象方,如果不採用橋接模式,一般我們的處理方式是直接使用繼承來實現,這樣雙方之間處於強連結,類之間關聯性極強,如要進行擴充套件,必然導致類結構急劇膨脹。採用橋接模式,正是為了避免這一情況的發生,將一方與橋繫結,即實現橋介面,另一方在抽象類中呼叫橋介面(指向的實現類),這樣橋方可以通過實現橋介面進行單方面擴充套件,而另一方可以繼承抽象類而單方面擴充套件,而之間的呼叫就從橋介面來作為突破口,不會受到雙方擴充套件的任何影響。