23种设计模式-结构型模式-桥接器

文章目录

简介

桥接器是一种结构型设计模式,可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构,从而能在开发时分别使用。

问题

假如你有一个几何形状Shape类,它有两个子类:圆形Cir­cle和方形Square。现在你想对类层次结构进行扩展,让它包含颜色属性,所以你打算创建 红色Red和 蓝色Blue的形状子类。但是,由于你已有两个子类,所以总共需要创建四个类才能覆盖所有组合,比如蓝色圆形Blue­Cir­cle和红色方形Red­Square。

在层次结构里新增形状和颜色都会导致代码复杂程度指数增长。比如添加三角形状,你需要新增两个子类,也就是每种颜色一个;此后新增一种新颜色需要新增三个子类,即每种形状一个。代码就越来越复杂。

解决方案

问题的根本原因是我们试图在两个独立的维度(形状与颜色)上扩展形状类。我们在使用类继承时经常遇到这样的问题。

桥接模式通过把继承改为组合的方式来解决这个问题。具体来说,就是抽取其中一个维度并让他成为独立的类层次,这样就可以在原来的类中引用这个新层次的对象,从而让一个类不需要拥有所有的状态和行为。

根据这种方法,我们可以把颜色相关的代码抽取到拥有红色和蓝色两个子类的颜色父类中,然后在形状类里添加一个指向某一颜色对象的引用成员变量。这个时候,形状类就可以把所有跟颜色相关的工作委派给引入的颜色对象。这样的引用就成为了形状和颜色之间的桥梁。在这之后,新增颜色都不再需要修改形状的类层次,反过来也一样。

示例

以上示例还比较简单,我们来看一个更复杂的示例,以便演示了桥接模式,看看它怎么拆分程序里同时管理设备和遥控器的复杂代码。设备Device类作为实现部分,而遥控器Remote类则作为抽象部分。

java 复制代码
/* 实现层级:设备接口规范 */
public interface Device {
    // 状态检测基础方法
    boolean isEnabled();
    void enable();    // Device接口定义
    void disable();
    
    // 媒体控制方法
    int getVolume();
    void setVolume(int percent);
    int getChannel();
    void setChannel(int channel);
}

/* 具体设备实现 */
class Tv implements Device {         // TV实现
    private boolean on = false;
    private int volume = 50;
    private int channel = 1;

    public boolean isEnabled() { return on; }
    public void enable() { on = true; }  // TV特有启动过程
    public void disable() { on = false; }
    
    public int getVolume() { return volume; }
    public void setVolume(int percent) { 
        volume = Math.max(0, Math.min(100, percent)); 
    }
    public int getChannel() { return channel; }
    public void setChannel(int ch) { 
        channel = Math.max(1, ch); 
    }
}

class Radio implements Device {     // Radio实现
    private boolean active = false;
    private int level = 30;
    
    public boolean isEnabled() { return active; }
    public void enable() { active = true; }
    public void disable() { active = false; }
    
    public int getVolume() { return level; }
    public void setVolume(int percent) {
        level = (percent > 100) ? 100 : Math.max(0, percent);
    }
    public int getChannel() { return 0; }  // 收音机无频道
    public void setChannel(int ch) {}      // 空实现
}

/* 抽象层级:遥控器抽象 */
abstract class RemoteControl {
    // 持有实现层对象的引用(关键结构)
    protected Device device;  
    
    public RemoteControl(Device device) {
        this.device = device;
    }
    
    // 电源切换核心逻辑
    public void togglePower() {
        if (device.isEnabled()) {
            device.disable();
        } else {
            device.enable();
        }
    }
    
    public void volumeUp() {
        device.setVolume(device.getVolume() + 10);
    }
    
    public void volumeDown() {
        device.setVolume(device.getVolume() - 10);
    }
    
    public void channelUp() {
        device.setChannel(device.getChannel() + 1);
    }
    
    public void channelDown() {
        device.setChannel(device.getChannel() - 1);
    }
}

/* 扩展抽象:高级遥控器(扩展功能) */
class AdvancedRemoteControl extends RemoteControl {
    public AdvancedRemoteControl(Device device) {
        super(device);
    }
    
    public void mute() {      // 新增静音功能
        device.setVolume(0);  // 通过接口操作设备
    }
}

// 客户端使用示例
public class Client {
    public static void main(String[] args) {
        Device tv = new Tv();
        RemoteControl basicRemote = new RemoteControl(tv);
        basicRemote.togglePower();   // 开启电视
        
        Device radio = new Radio();
        AdvancedRemoteControl advancedRemote = new AdvancedRemoteControl(radio);
        advancedRemote.mute();       // 设置静音
    }
}

总结

  1. 抽象部分(Abstraction):提供高层控制逻辑,依赖完成底层实际工作的具体实现对象
  2. 实现部分(Implementation):为所有具体实现声明通用接口。抽象部分仅能通过在这里声明的方法和实现对象交互。抽象部分可以列出和实现部分一样的方法,但是抽象部分通常声明一些复杂的行为,这些行为依赖于多种由实现部分声明的操作。
  3. 具体实现(Concrete Implementations)中包括特定平台的代码。
  4. 精确抽象(Refined Abstraction)提供控制逻辑的变体。和它的父类一样,它们通过通用实现接口与不同的实现进行交互。
  5. 通常情况下,客户端(Client)仅关心如何与抽象部分合作 。但是,客户端需要把抽象对象和一个实现对象连接起来。
相关推荐
Boilermaker19922 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
Cherry的跨界思维2 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
alonewolf_992 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
一嘴一个橘子2 小时前
spring-aop 的 基础使用(啥是增强类、切点、切面)- 2
java
sheji34163 小时前
【开题答辩全过程】以 中医药文化科普系统为例,包含答辩的问题和答案
java
恋爱绝缘体13 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit
xiaolyuh1233 小时前
Spring 框架 核心架构设计 深度详解
spring·设计模式·spring 设计模式
wszy18093 小时前
新文章标签:让用户一眼发现最新内容
java·python·harmonyos
wszy18094 小时前
顶部标题栏的设计与实现:让用户知道自己在哪
java·python·react native·harmonyos
贺biubiu4 小时前
2025 年终总结|总有那么一个人,会让你千里奔赴...
android·程序员·年终总结