跳至主要內容

桥接模式

Mr.Hope...大约 4 分钟

桥接是一种结构型设计模式, 可将业务逻辑或一个大类拆分为不同的层次结构, 从而能独立地进行开发。

层次结构中的第一层 (通常称为抽象部分) 将包含对第二层 (实现部分) 对象的引用。 抽象部分将能将一些 (有时是绝大部分) 对自己的调用委派给实现部分的对象。 所有的实现部分都有一个通用接口, 因此它们能在抽象部分内部相互替换。

使用示例: 桥接模式在处理跨平台应用、 支持多种类型的数据库服务器或与多个特定种类 (例如云平台和社交网络等) 的 API 供应商协作时会特别有用。

识别方法: 桥接可以通过一些控制实体及其所依赖的多个不同平台之间的明确区别来进行识别。

设备和遥控器之间的桥接

本例展示了遥控器及其所控制的设备的类之间的分离。

遥控器是抽象部分, 设备则是其实现部分。 由于有通用的接口, 同一遥控器可与不同的设备合作, 反过来也一样。

桥接模式允许在不改动另一层次代码的前提下修改已有类, 甚至创建新类。

项目结构

image-20240428150758244

devices

devices/Device.java: 所有设备的通用接口

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: 收音机

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 this.volume = Math.max(volume, 0);
    }

    @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("| 我是收音机。");
        System.out.println("| 我目前 " + (on ? "启用" : "禁用"));
        System.out.println("| 当前音量为 " + volume + "%");
        System.out.println("| 当前频道是 " + channel);
        System.out.println("------------------------------------\n");
    }
}

devices/Tv.java: 电视机

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 this.volume = Math.max(volume, 0);
    }

    @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("| 我是电视机。");
        System.out.println("| 我目前 " + (on ? "启用" : "禁用"));
        System.out.println("| 当前音量为 " + volume + "%");
        System.out.println("| 当前频道是 " + channel);
        System.out.println("------------------------------------\n");
    }
}

remotes

remotes/Remote.java: 所有遥控器的通用接口

// 遥控器,抽象出来了遥控器接口
public interface Remote {
    void power();

    void volumeDown();

    void volumeUp();

    void channelDown();

    void channelUp();
}

remotes/BasicRemote.java: 基础遥控器

// 具体的实现类,需要与桥接的接口进行对接(组合)
public class BasicRemote implements Remote{
    //体现桥接模式的地方:组合,而非继承
    protected Device device;

    public BasicRemote() {}

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

    @Override
    public void power() {
        System.out.println("遥控器:电源切换");
        if (device.isEnabled()) {
            device.disable();
        } else {
            device.enable();
        }
    }

    @Override
    public void volumeDown() {
        System.out.println("遥控:降低音量");
        device.setVolume(device.getVolume() - 10);
    }

    @Override
    public void volumeUp() {
        System.out.println("遥控:调高音量");
        device.setVolume(device.getVolume() + 10);
    }

    @Override
    public void channelDown() {
        System.out.println("遥控:上一个频道");
        device.setChannel(device.getChannel() - 1);
    }

    @Override
    public void channelUp() {
        System.out.println("遥控:下一个频道");
        device.setChannel(device.getChannel() + 1);
    }
}

remotes/AdvancedRemote.java: 高级遥控器

public class AdvancedRemote extends BasicRemote
{
    public AdvancedRemote(Device device) {
        super.device = device;
    }

    public void mute() {
        System.out.println("遥控:静音");
        device.setVolume(0);
    }
}

Demo

public class Main {
    public static void main(String[] args) {
        System.out.println("TV测试=============================");
        testDevice(new Tv());

        System.out.println("收音机测试=============================");
        testDevice(new Radio());
    }

    public static void testDevice(Device device) {
        System.out.println("使用基本遥控器进行测试。");
        BasicRemote basicRemote = new BasicRemote(device);
        basicRemote.power();
        device.printStatus();

        System.out.println("使用高级遥控器进行测试。");
        AdvancedRemote advancedRemote = new AdvancedRemote(device);
        advancedRemote.power();
        advancedRemote.mute();
        device.printStatus();
    }
}

结果:

TV测试=============================
使用基本遥控器进行测试。
遥控器:电源切换
------------------------------------
| 我是电视机。
| 我目前 启用
| 当前音量为 30%
| 当前频道是 1
------------------------------------

使用高级遥控器进行测试。
遥控器:电源切换
遥控:静音
------------------------------------
| 我是电视机。
| 我目前 禁用
| 当前音量为 0%
| 当前频道是 1
------------------------------------

收音机测试=============================
使用基本遥控器进行测试。
遥控器:电源切换
------------------------------------
| 我是收音机。
| 我目前 启用
| 当前音量为 30%
| 当前频道是 1
------------------------------------

使用高级遥控器进行测试。
遥控器:电源切换
遥控:静音
------------------------------------
| 我是收音机。
| 我目前 禁用
| 当前音量为 0%
| 当前频道是 1
------------------------------------