橋模式(學習筆記)

  1. 意圖

  將抽象部分與它的實現部分分離,使它們能夠獨立的變化java

  2. 動機

  如左圖所示,若是此時需求變化,假設有n個形狀(圓形,方形,長方形...),增長m個顏色,則須要額外增長(n+1)*m個類,會形成類爆炸。另外,代碼後期維護成本很高。橋模式使用組合代替繼承來解決這個問題。這樣只會增長m個新類,代碼易於維護。數據庫

 

  

  3. 適用性

  • 不但願抽象和它的實現部分有一個固定的綁定關係
  • 類的抽象以及它的實現都應該經過生成子類的方法加以擴充。這時,Bridge模式使你能夠對不一樣的抽象接口和實現部分進行組合,並分別對它們進行擴充
  • 對一個抽象的實現部分的修改應對客戶不產生影響,即客戶代碼不須要從新編譯

  4. 結構

  

  5. 效果

  1) 分離接口及其實現部分服務器

  2) 提升可擴充性網絡

  3) 若是須要在運行時切換不一樣的方法,可以使用橋接模式ide

    橋模式能夠替換抽象部分中的實現對象this

  4) 開閉原則。 能夠新增抽象部分和實現部分, 且它們之間不會相互影響。spa

  5) 單一職責原則。 抽象部分專一於處理高層邏輯, 實現部分處理平臺細節。設計

  6. 代碼實現

  devices/Device.java: 全部設備的通用接口  code

package bridge.devices;

/**
 * @author GaoMing
 * @date 2021/7/12 - 10:59
 */
public interface Device {
    boolean isEnabled();

    void enable();

    void disable();

    int getVolume();

    void setVolume(int percent);

    int getChannel();

    void setChannel(int channel);

    void printStatus();
}

  devices/Radio.java: 收音機對象

package bridge.devices;

/**
 * @author GaoMing
 * @date 2021/7/12 - 10:56
 */
public class Radio implements Device{
    private boolean on = false;
    private int volume = 30;
    private int channel = 1;

    @Override
    public boolean isEnabled() {
        return on;
    }

    @Override
    public void enable() {
        on = true;
    }

    @Override
    public void disable() {
        on = false;
    }

    @Override
    public int getVolume() {
        return volume;
    }

    @Override
    public void setVolume(int volume) {
        if (volume > 100) {
            this.volume = 100;
        } else if (volume < 0) {
            this.volume = 0;
        } else {
            this.volume = volume;
        }
    }

    @Override
    public int getChannel() {
        return channel;
    }

    @Override
    public void setChannel(int channel) {
        this.channel = channel;
    }

    @Override
    public void printStatus() {
        System.out.println("------------------------------------");
        System.out.println("| I'm radio.");
        System.out.println("| I'm " + (on ? "enabled" : "disabled"));
        System.out.println("| Current volume is " + volume + "%");
        System.out.println("| Current channel is " + channel);
        System.out.println("------------------------------------\n");
    }
}

  devices/Tv.java: 電視機  

package bridge.devices;

/**
 * @author GaoMing
 * @date 2021/7/12 - 10:56
 */
public class TV implements Device{
    private boolean on = false;
    private int volume = 30;
    private int channel = 1;

    @Override
    public boolean isEnabled() {
        return on;
    }

    @Override
    public void enable() {
        on = true;
    }

    @Override
    public void disable() {
        on = false;
    }

    @Override
    public int getVolume() {
        return volume;
    }

    @Override
    public void setVolume(int volume) {
        if (volume > 100) {
            this.volume = 100;
        } else if (volume < 0) {
            this.volume = 0;
        } else {
            this.volume = volume;
        }
    }

    @Override
    public int getChannel() {
        return channel;
    }

    @Override
    public void setChannel(int channel) {
        this.channel = channel;
    }

    @Override
    public void printStatus() {
        System.out.println("------------------------------------");
        System.out.println("| I'm TV set.");
        System.out.println("| I'm " + (on ? "enabled" : "disabled"));
        System.out.println("| Current volume is " + volume + "%");
        System.out.println("| Current channel is " + channel);
        System.out.println("------------------------------------\n");
    }
}

   remotes/Remote.java: 全部遠程控制器的通用接口

package bridge.remotes;

/**
 * @author GaoMing
 * @date 2021/7/12 - 11:02
 */
public interface Remote {
    void power();

    void volumeDown();

    void volumeUp();

    void channelDown();

    void channelUp();
}

  remotes/BasicRemote.java: 基礎遠程控制器

package bridge.remotes;

import bridge.devices.Device;

/**
 * @author GaoMing
 * @date 2021/7/12 - 10:57
 */
public class BasicRemote implements Remote{
    protected Device device;

    public BasicRemote() {}

    public BasicRemote(Device device) {
        this.device = device;
    }

    @Override
    public void power() {
        System.out.println("Remote: power toggle");
        if (device.isEnabled()) {
            device.disable();
        } else {
            device.enable();
        }
    }

    @Override
    public void volumeDown() {
        System.out.println("Remote: volume down");
        device.setVolume(device.getVolume() - 10);
    }

    @Override
    public void volumeUp() {
        System.out.println("Remote: volume up");
        device.setVolume(device.getVolume() + 10);
    }

    @Override
    public void channelDown() {
        System.out.println("Remote: channel down");
        device.setChannel(device.getChannel() - 1);
    }

    @Override
    public void channelUp() {
        System.out.println("Remote: channel up");
        device.setChannel(device.getChannel() + 1);
    }
}

  remotes/AdvancedRemote.java: 高級遠程控制器

package bridge.remotes;

import bridge.devices.Device;

/**
 * @author GaoMing
 * @date 2021/7/12 - 10:57
 */
public class AdvancedRemote extends BasicRemote{
    public AdvancedRemote(Device device) {
        super.device = device;
    }

    public void mute() {
        System.out.println("Remote: mute");
        device.setVolume(0);
    }
}

  Demo.java: 客戶端代碼

package bridge;

import bridge.devices.Device;
import bridge.devices.Radio;
import bridge.devices.TV;
import bridge.remotes.AdvancedRemote;
import bridge.remotes.BasicRemote;

/**
 * @author GaoMing
 * @date 2021/7/12 - 10:56
 */
public class Demo {
    public static void main(String[] args) {
        testDevice(new TV());
        testDevice(new Radio());
    }

    public static void testDevice(Device device) {
        System.out.println("Tests with basic remote.");
        BasicRemote basicRemote = new BasicRemote(device);
        basicRemote.power();
        device.printStatus();

        System.out.println("Tests with advanced remote.");
        AdvancedRemote advancedRemote = new AdvancedRemote(device);
        advancedRemote.power();
        advancedRemote.mute();
        device.printStatus();
    }
}

  執行結果

Tests with basic remote.
Remote: power toggle
------------------------------------
| I'm TV set.
| I'm enabled
| Current volume is 30%
| Current channel is 1
------------------------------------

Tests with advanced remote.
Remote: power toggle
Remote: mute
------------------------------------
| I'm TV set.
| I'm disabled
| Current volume is 0%
| Current channel is 1
------------------------------------

Tests with basic remote.
Remote: power toggle
------------------------------------
| I'm radio.
| I'm enabled
| Current volume is 30%
| Current channel is 1
------------------------------------

Tests with advanced remote.
Remote: power toggle
Remote: mute
------------------------------------
| I'm radio.
| I'm disabled
| Current volume is 0%
| Current channel is 1
------------------------------------

 

  7. 與其餘模式的關係

  • 能夠結合使用生成器模式和橋接模式: 主管類負責抽象工做, 各類不一樣的生成器負責實現工做
  • 能夠將抽象工廠模式和橋接搭配使用。 若是由橋接定義的抽象只能與特定實現合做, 這一模式搭配就很是有用。 在這種狀況下, 抽象工廠能夠對這些關係進行封裝, 而且對客戶端代碼隱藏其複雜性
  • 橋接模式一般會於開發前期進行設計, 使你可以將程序的各個部分獨立開來以便開發。 另外一方面, 適配器模式一般在已有程序中使用, 讓相互不兼容的類能很好地合做

  8. 已知應用

  使用示例: 橋接模式在處理跨平臺應用、 支持多種類型的數據庫服務器或與多個特定種類 (例如雲平臺和社交網絡等) 的 API 供應商協做時會特別有用

  識別方法: 橋接能夠經過一些控制實體及其所依賴的多個不一樣平臺之間的明確區別來進行識別

相關文章
相關標籤/搜索