23种设计模式之【桥接模式】-核心原理与 Java实践

文章目录

桥接模式(Bridge Pattern)

桥接模式是 23 种设计模式中的一种结构型模式,其核心思想是将抽象部分与实现部分分离,使它们可以独立变化。这种模式通过引入 "桥接"(抽象与实现之间的关联),解决了因多维度变化导致的类爆炸问题,提高了系统的灵活性和可扩展性。

核心原理

  • 抽象化角色(Abstraction):
    定义抽象类的接口,持有一个对实现化角色的引用
    负责定义抽象部分的业务方法,不涉及具体实现
  • 扩展抽象化角色(RefinedAbstraction):
    继承抽象化角色,扩展抽象部分的功能
    实现父类中的抽象方法,并可能添加新的方法
  • 实现化角色(Implementor):
    定义实现部分的接口,提供基本操作
    不直接与抽象化角色中的业务方法对应,而是提供底层实现
  • 具体实现化角色(ConcreteImplementor):
    实现实现化角色的接口,提供具体的业务实现
    可以有多个不同的具体实现类

桥接模式的核心是 "分离抽象与实现",通过抽象类引用实现接口,使抽象和实现可以沿着各自的维度独立扩展,避免了多维度组合导致的类数量爆炸。

Java 实践示例

以 "电子设备与遥控器" 为例实现桥接模式:

抽象维度:基础遥控器、高级遥控器(支持更多功能)

实现维度:电视、收音机等不同电子设备

通过桥接将遥控器(抽象)与设备(实现)分离,使两者可独立扩展

java 复制代码
package com.example.demo;

public class BridgePattern {
    public static void main(String[] args) {
        // 创建具体设备
        Device tv = new TV();
        Device radio = new Radio();

        // 基础遥控器控制电视
        RemoteControl basicRemoteForTV = new BasicRemoteControl(tv);
        System.out.println("=== 基础遥控器控制电视 ===");
        basicRemoteForTV.powerOn();
        basicRemoteForTV.setChannel(5);
        basicRemoteForTV.powerOff();

        // 高级遥控器控制收音机
        RemoteControl advancedRemoteForRadio = new AdvancedRemoteControl(radio);
        System.out.println("\n=== 高级遥控器控制收音机 ===");
        advancedRemoteForRadio.powerOn();
        advancedRemoteForRadio.setChannel(88.5);
        ((AdvancedRemoteControl) advancedRemoteForRadio).setVolume(20);
        advancedRemoteForRadio.powerOff();

        //=== 基础遥控器控制电视 ===
        //电视已打开
        //电视频道已设置为:5
        //电视已关闭
        //
        //=== 高级遥控器控制收音机 ===
        //收音机已打开
        //收音机音量已设置为:15
        //收音机频率已设置为:88.5MHz
        //收音机音量已设置为:20
        //收音机已关闭
    }

    // 实现化角色:设备接口(定义设备的基本操作)
    public interface Device {
        void powerOn();
        void powerOff();
        void setChannel(double channel);
        void setVolume(int volume);
    }

    // 具体实现:电视
    public static class TV implements Device {
        private boolean isOn = false;
        private int channel = 1;
        private int volume = 10;

        @Override
        public void powerOn() {
            isOn = true;
            System.out.println("电视已打开");
        }

        @Override
        public void powerOff() {
            isOn = false;
            System.out.println("电视已关闭");
        }

        @Override
        public void setChannel(double channel) {
            if (isOn) {
                this.channel = (int) channel;
                System.out.println("电视频道已设置为:" + this.channel);
            } else {
                System.out.println("请先打开电视");
            }
        }

        @Override
        public void setVolume(int volume) {
            if (isOn) {
                this.volume = volume;
                System.out.println("电视音量已设置为:" + this.volume);
            }
        }
    }

    // 具体实现:收音机
    public static class Radio implements Device {
        private boolean isOn = false;
        private double frequency = 87.5;
        private int volume = 5;

        @Override
        public void powerOn() {
            isOn = true;
            System.out.println("收音机已打开");
        }

        @Override
        public void powerOff() {
            isOn = false;
            System.out.println("收音机已关闭");
        }

        @Override
        public void setChannel(double frequency) {
            if (isOn) {
                this.frequency = frequency;
                System.out.println("收音机频率已设置为:" + this.frequency + "MHz");
            } else {
                System.out.println("请先打开收音机");
            }
        }

        @Override
        public void setVolume(int volume) {
            if (isOn) {
                this.volume = volume;
                System.out.println("收音机音量已设置为:" + this.volume);
            }
        }
    }

    // 抽象化角色:遥控器抽象类
    public abstract static class RemoteControl {
        // 持有设备接口的引用(桥接点)
        protected Device device;

        // 通过构造函数注入设备
        public RemoteControl(Device device) {
            this.device = device;
        }

        // 抽象方法:开机
        public abstract void powerOn();

        // 抽象方法:关机
        public abstract void powerOff();

        // 抽象方法:设置频道
        public abstract void setChannel(double channel);
    }

    // 扩展抽象:基础遥控器
    public static class BasicRemoteControl extends RemoteControl {
        public BasicRemoteControl(Device device) {
            super(device);
        }

        @Override
        public void powerOn() {
            device.powerOn();
        }

        @Override
        public void powerOff() {
            device.powerOff();
        }

        @Override
        public void setChannel(double channel) {
            device.setChannel(channel);
        }
    }

    // 扩展抽象:高级遥控器(新增音量调节功能)
    public static class AdvancedRemoteControl extends RemoteControl {
        public AdvancedRemoteControl(Device device) {
            super(device);
        }

        @Override
        public void powerOn() {
            device.powerOn();
            // 高级功能:开机自动调节到适中音量
            device.setVolume(15);
        }

        @Override
        public void powerOff() {
            device.powerOff();
        }

        @Override
        public void setChannel(double channel) {
            device.setChannel(channel);
        }

        // 新增功能:调节音量
        public void setVolume(int volume) {
            device.setVolume(volume);
        }
    }
}

桥接模式的特点

优点:

分离抽象与实现:抽象部分和实现部分可独立扩展,互不影响

减少类数量:避免多维度组合导致的类爆炸(如 2 种遥控器 ×2 种设备 = 4 个类,而非传统继承的 2+2+2=6 个类)

提高灵活性:可动态切换实现,抽象部分可透明地使用不同实现

符合开闭原则:新增抽象或实现时无需修改原有代码

缺点:

增加系统复杂度:引入额外的抽象层和桥接点,理解难度提高

要求正确识别系统的两个独立变化维度,设计难度较大

与适配器模式的区别:

桥接模式:在设计初期就考虑分离抽象与实现,为了扩展

适配器模式:在系统设计完成后解决接口不兼容问题,为了兼容

桥接模式的应用场景

多维度变化的系统:

当系统存在两个或多个独立变化的维度(如形状 × 颜色、操作系统 × 软件)

例如:图形系统中,形状(圆形、矩形)和渲染方式(软件渲染、硬件渲染)是两个独立维度

避免继承爆炸:

当使用继承会导致大量子类(如 4 种品牌 ×3 种类型 = 12 个子类)

例如:电器产品(冰箱、洗衣机)与品牌(海尔、美的)的组合

框架设计:

框架需要为抽象部分和实现部分提供扩展点

例如:Java 的 AWT 中,Component(抽象)与Peer(实现)的分离,支持不同平台的 UI 实现

数据库驱动:

数据库操作接口(抽象)与不同数据库驱动(实现)的分离

例如:JDBC 中Driver接口与不同数据库的驱动实现

桥接模式是应对 "多维度变化" 场景的最佳方案,通过分离抽象与实现,使系统可以沿着多个维度独立扩展,同时避免了类数量的急剧增加。在设计初期识别出系统的独立变化维度,是成功应用桥接模式的关键。

相关推荐
汤姆yu2 小时前
2025版基于springboot的家政服务预约系统
java·spring boot·后端
sheji34162 小时前
【开题答辩全过程】以 J2EE应用于母婴健康管理系统的开发与实施为例,包含答辩的问题和答案
java·java-ee
Gss7773 小时前
Tomcat
java·tomcat
tuokuac3 小时前
MyBatis“别名扫描”功能
java·mybatis
艾莉丝努力练剑3 小时前
【编码表 && STL】C++编程基石:从字符编码表到STL标准库的完整入门指南
java·linux·c++
Moshow郑锴3 小时前
IDEA/WebStorm 卡顿问题与启动参数调优指南
java·jvm·intellij-idea·webstorm
努力也学不会java3 小时前
【设计模式】中介者模式
java·设计模式·中介者模式
努力努力再努力wz3 小时前
【C++进阶系列】:位图和布隆过滤器(附模拟实现的源码)
java·linux·运维·开发语言·数据结构·c++
Yeats_Liao3 小时前
Java网络编程(三):NIO核心组件Channel通道详解
java·网络·nio