天天看點

拒絕一坨代碼——橋接模式(Bridge)

概述:

所謂的橋接,是指中間有一座像橋一樣的媒介,連接配接着橋兩頭的事物。從代碼設計角度來講,一般在拿到需求後,需要抽象出 變化的部分和固定的部分。在橋接模式中,“橋”連接配接的兩頭事物,屬于變化的部分。兩個變化的事物通過一座“橋”連接配接,進行了 解耦。

定義:

将抽象部分與它的實作部分分離,使它們都可以獨立地變化

UML圖:

拒絕一坨代碼——橋接模式(Bridge)

橋接模式将抽象部分和實作部分進行分離,使它們可以獨立地變化。

中間的聚合線,就是"橋"。

橋的左邊 Abstraction: 抽象化角色,指忽略一些資訊,把不同的實體當作同樣的實體對待

橋的右邊 Implementor:實作化角色,定義角色必需的行為和屬性,與實作化是一對互逆的概念,實作化産生的對象比抽象化更具體,是對抽象化事物的進一步具體的産物

适用範圍:

1、一個類可以有多個角度分類,每一種角度都可以進行擴充變化

2、如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,又想避免在兩個層次之間建立靜态的繼承聯系,通過橋接模式可以使它們在抽象層建立一個關聯關系

使用場景:

比如支付場景中,有微信支付、支付寶支付、銀聯支付等,支付方式有指紋、掃臉、密碼支付。可以把微信、支付寶等支付看成是 抽象化角色(Abstraction),支付方式密碼、指紋等看成是 實作化角色(Implementor)。

比如OA消息系統中,可以通過短信、郵件等方式進行消息發送,消息業務類型有 普通、緊急、特急類型。發送方式可以看成是 抽象化角色(Abstraction),消息業務類型可以看成是 實作化角色(Implementor)

以及Java應用的JDBC設計,其實也是橋接模式,uml圖如下:

拒絕一坨代碼——橋接模式(Bridge)

優缺點:

優點:

1、抽象和實作分離,使其可以各自變化

2、解決了多重繼承帶來的不靈活性

3、擴充能力增強

缺點:

1、增加對系統的了解和設計難度

舉例:

有這樣一個需求,通過短信、郵件發送消息,我們很自然的會建立如下的設計圖:

拒絕一坨代碼——橋接模式(Bridge)

此時增加一種緊急消息,UML圖變成如下形式:

拒絕一坨代碼——橋接模式(Bridge)

假設再增加一個 特急消息,UML圖以此類推,會變成如下形式:

拒絕一坨代碼——橋接模式(Bridge)

這裡采用了多重繼承的方式進行需求實作,擴充起來非常不友善。

其實在需求實作中我們可以發現,消息發送方式 短信、郵件這一次元是可以獨自變化的,與具體消息類型可以區分開,這樣再來一個需求,增加電話通知 這樣的消息發送方式也沒關系。

同樣的消息業務類型,也是可以進行獨立變化,普通、加急、特急、再加一個董事長緊急消息的需求  也沒關系,照樣可以靈活擴充。

下面我們用橋接模式畫出UML圖:

拒絕一坨代碼——橋接模式(Bridge)

采用橋接模式後,結構變得清晰很多,并且靈活性也相應的提升了。

代碼實作:

實作化角色:

/**
 * 橋接模式-實作化角色
 */
public interface MessageImplementor {
    void send(String msg, String to);
}
           

具體實作:

短信方式:

public class MessageSMS implements MessageImplementor {
    @Override
    public void send(String msg, String to) {
        System.out.println("SMS:");
        System.out.println("to: " + to);
        System.out.println("content: " + msg);
    }
}
           

郵件方式:

public class MessageMail  implements MessageImplementor {
    @Override
    public void send(String msg, String to) {
        System.out.println("Mail:");
        System.out.println("to: " + to);
        System.out.println("content: " + msg);
    }
}
           

抽象化角色:

/**
 * 消息抽象
 */
public abstract class AbstractMessage {
    //消息實作
    protected MessageImplementor messageImplementor;

    public AbstractMessage() {
    }

    public void setMessageImplementor(MessageImplementor messageImplementor){
        this.messageImplementor = messageImplementor;
    }

    public abstract void sendMsg(String msg, String to);
}
           

普通消息:

public class NormalMessage extends AbstractMessage{
    @Override
    public void sendMsg(String msg, String to) {
        msg = "Normal-" + msg;
        messageImplementor.send(msg, to);
    }
}
           

加急消息:

public class UrgencyMessage extends AbstractMessage {
    @Override
    public void sendMsg(String msg, String to) {
        msg = "Urgency!" + msg;
        messageImplementor.send(msg, to);
    }
}
           

特急消息:

public class SpecialUrgencyMessage extends AbstractMessage {
    @Override
    public void sendMsg(String msg, String to) {
        msg = "Special Urgency!!" + msg;
        messageImplementor.send(msg, to);
    }
}
           

測試類:

public class BridgeTest {
    public static void main(String[] args) {
        //短信方式發送
        MessageImplementor messageSMS = new MessageSMS();
        //普通消息發送
        AbstractMessage normalMessage = new NormalMessage();
        normalMessage.setMessageImplementor(messageSMS);
        normalMessage.sendMsg("請你吃飯", "13312341234");
        //緊急消息發送
        AbstractMessage urgencyMessage = new UrgencyMessage();
        urgencyMessage.setMessageImplementor(messageSMS);
        urgencyMessage.sendMsg("急着請你吃飯", "13312341234");
        //特急消息發送
        AbstractMessage specialUrgencyMessage = new SpecialUrgencyMessage();
        specialUrgencyMessage.setMessageImplementor(messageSMS);
        specialUrgencyMessage.sendMsg("非常迫切的想請你吃飯", "13312341234");
    }
}
           

小結:

記住 橋接模式是 抽象和實作分離的概念就行

繼續閱讀