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)仅关心如何与抽象部分合作 。但是,客户端需要把抽象对象和一个实现对象连接起来。
相关推荐
wei_shuo4 分钟前
飞算 JavaAI 开发助手:深度学习驱动下的 Java 全链路智能开发新范式
java·开发语言·飞算javaai
断剑重铸之日17 分钟前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安19 分钟前
Android Library Maven 发布完整流程指南
android
岁月玲珑25 分钟前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
欧阳秦穆26 分钟前
apoc-5.24.0-extended.jar 和 apoc-4.4.0.36-all.jar 啥区别
java·jar
岁忧37 分钟前
(LeetCode 面试经典 150 题 ) 58. 最后一个单词的长度 (字符串)
java·c++·算法·leetcode·面试·go
Java初学者小白41 分钟前
秋招Day14 - Redis - 应用
java·数据库·redis·缓存
代码老y1 小时前
Spring Boot + 本地部署大模型实现:优化与性能提升
java·spring boot·后端
码农秋1 小时前
设计模式系列(10):结构型模式 - 桥接模式(Bridge)
设计模式·桥接模式
GodKeyNet1 小时前
设计模式-桥接模式
java·设计模式·桥接模式