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)仅关心如何与抽象部分合作 。但是,客户端需要把抽象对象和一个实现对象连接起来。
相关推荐
期待のcode13 小时前
MyBatisX插件
java·数据库·后端·mybatis·springboot
Lei活在当下16 小时前
【项目踩坑实录】并发环境下,Glide缓存引起的图片加载异常
android·debug·glide
醇氧16 小时前
【Windows】优雅启动:解析一个 Java 服务的后台启动脚本
java·开发语言·windows
sunxunyong16 小时前
doris运维命令
java·运维·数据库
菜鸟起航ing16 小时前
Spring AI 全方位指南:从基础入门到高级实战
java·人工智能·spring
古城小栈16 小时前
Docker 多阶段构建:Go_Java 镜像瘦身运动
java·docker·golang
MapGIS技术支持16 小时前
MapGIS Objects Java计算一个三维点到平面的距离
java·开发语言·平面·制图·mapgis
Coder_Boy_16 小时前
业务导向型技术日志首日记录(业务中使用的技术栈)
java·驱动开发·微服务
盖世英雄酱5813618 小时前
springboot 项目 从jdk 8 升级到jdk21 会面临哪些问题
java·后端
济南壹软网络科技有限公司18 小时前
企业级盲盒系统:Java高并发架构在多元化抽奖电商中的设计与实践
java·架构·开源源码·盲盒源码·盲盒h5·盲盒app