设计模式系列(10):结构型模式 - 桥接模式(Bridge)

发布于:2025-07-04 ⋅ 阅读:(21) ⋅ 点赞:(0)

系列导读:在学习了接口适配后,我们来看如何处理抽象与实现的分离问题。桥接模式解决的是"多维度变化"的设计难题。

解决什么问题:将抽象部分与实现部分分离,使它们都可以独立变化。避免在多个维度上变化时出现类爆炸问题。

想象一下,你要设计一个图形绘制系统,既要支持不同的形状(圆形、矩形),又要支持不同的绘制方式(Windows绘制、Linux绘制)。如果用继承,你需要WindowsCircle、LinuxCircle、WindowsRectangle、LinuxRectangle等类,随着形状和平台的增加,类的数量会爆炸式增长。

桥接模式通过将"形状"和"绘制方式"分离成两个独立的层次结构,用组合代替继承,让两个维度可以独立变化和扩展。

本文在系列中的位置

  • 前置知识:适配器模式
  • 系列角色:结构型模式核心
  • 难度等级:★★★★☆(概念较抽象,需要理解抽象与实现分离)
  • 后续学习:组合模式

目录

1. 模式概述

桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。这种模式通过组合的方式,而不是继承的方式,来实现抽象和实现的解耦。桥接模式常用于需要多维度扩展的系统,能够有效避免类爆炸问题。

定义

桥接模式将抽象部分与实现部分分离,使它们都可以独立地变化。通过在抽象层中持有实现层的引用,实现抽象和实现的解耦,便于系统的扩展和维护。

目的

  • 分离抽象与实现,避免继承导致的类爆炸
  • 支持抽象和实现的独立扩展,提升系统灵活性
  • 降低系统耦合度,便于维护和升级

2. 使用场景

桥接模式适用于以下场景:

  1. 抽象和实现分离

    • 需要将抽象和实现分离,便于独立扩展。
    • 需要支持多种实现方式,避免继承的局限性。
    • 需要在运行时切换实现。
  2. 多维度变化

    • 系统存在多个变化维度,如形状和颜色、平台和功能等。
    • 需要避免因多维扩展导致的类爆炸。
    • 需要灵活组合不同维度的实现。
  3. 运行时绑定

    • 需要在运行时动态切换实现。
    • 需要支持插件化、可插拔架构。
    • 需要动态改变实现方式。

真实业务背景举例:

  • 跨平台UI库,既要支持多种控件类型(如按钮、文本框),又要支持多种操作系统(如Windows、Linux、Mac),通过桥接模式实现控件与平台的解耦。
  • 图形绘制系统,既要支持多种图形(如圆形、矩形),又要支持多种绘图API(如OpenGL、DirectX),通过桥接模式灵活组合。
  • 云存储平台支持多种存储后端(如本地磁盘、阿里云OSS、亚马逊S3),通过桥接模式灵活切换存储实现。

3. 优缺点分析

优点

  1. 解耦:抽象和实现分离,降低代码耦合度。提高代码可维护性和扩展性。支持独立演化和升级。
  2. 扩展性:支持多维度独立扩展,符合开闭原则。避免继承导致的类爆炸。易于添加新的抽象或实现。
  3. 灵活性:支持运行时切换实现,提升系统灵活性。支持动态组合不同实现。便于实现插件化架构。

缺点

  1. 复杂性提升:增加系统结构复杂度。需要合理设计抽象和实现层次。增加理解和维护难度。
  2. 设计难度:需要合理划分抽象和实现。需要处理两者之间的关系。需要保持接口一致性。
  3. 维护成本:需要维护多个类和接口。需要处理版本兼容和扩展问题。需要保证系统整体一致性。

4. 实际应用案例

  1. GUI框架:跨平台控件(如按钮、文本框在不同操作系统下的实现)、主题切换(如不同UI主题的动态切换)、控件风格扩展(如扁平风格、拟物风格等)。
  2. 数据库访问:支持多种数据库类型(MySQL、Oracle、SQL Server等)、多种连接方式(JDBC、ODBC等)、多种查询方式(SQL、NoSQL等)。
  3. 消息系统:支持多种消息类型(文本、图片、视频等)、多种发送方式(HTTP、MQ、WebSocket等)、多种处理方式(同步、异步等)。
  4. 文件系统:支持多种存储方式(本地、云端、分布式等)、多种文件格式(txt、pdf、doc等)、多种访问方式(读、写、删除等)。

5. 结构与UML类图

@startuml
package "Bridge Pattern" #DDDDDD {
  interface DrawingAPI {
    + drawCircle(x: int, y: int, radius: int): void
    + drawRectangle(x: int, y: int, width: int, height: int): void
  }
  class WindowsDrawingAPI implements DrawingAPI
  class LinuxDrawingAPI implements DrawingAPI
  abstract class Shape {
    # drawingAPI: DrawingAPI
    + draw(): void
  }
  class Circle extends Shape
  class Rectangle extends Shape
  DrawingAPI <|.. WindowsDrawingAPI
  DrawingAPI <|.. LinuxDrawingAPI
  Shape <|-- Circle
  Shape <|-- Rectangle
  Shape o-- DrawingAPI : drawingAPI
}
@enduml

6. 代码示例

6.1 基本结构示例

业务背景: 实现抽象与实现分离的基本结构,支持运行时切换实现。

package com.example.patterns.bridge;

import java.util.Objects;

// 实现接口,定义实现层的操作
public interface Implementor {
    /**
     * 实现层的具体操作
     * 业务含义:底层平台或品牌的具体实现
     */
    void operationImpl();
    
    /**
     * 获取实现类型
     */
    String getType();
}

// 具体实现A,实现Implementor接口
public class ConcreteImplementorA implements Implementor {
    @Override
    public void operationImpl() {
        try {
            // 具体实现A的业务逻辑
            System.out.println("ConcreteImplementorA operation - 执行实现A的业务逻辑");
        } catch (Exception e) {
            System.err.println("ImplementorA operation failed: " + e.getMessage());
            throw new RuntimeException("实现A操作失败", e);
        }
    }
    
    @Override
    public String getType() {
        return "ImplementorA";
    }
}

// 具体实现B,实现Implementor接口
public class ConcreteImplementorB implements Implementor {
    @Override
    public void operationImpl() {
        try {
            // 具体实现B的业务逻辑
            System.out.println("ConcreteImplementorB operation - 执行实现B的业务逻辑");
        } catch (Exception e) {
            System.err.println("ImplementorB operation failed: " + e.getMessage());
            throw new RuntimeException("实现B操作失败", e);
        }
    }
    
    @Override
    public String getType() {
        return "ImplementorB";
    }
}

// 抽象类,持有实现接口的引用
public abstract class Abstraction {
    protected final Implementor implementor;
    
    /**
     * 构造方法注入实现层,便于运行时切换
     */
    public Abstraction(Implementor implementor) {
        this.implementor = Objects.requireNonNull(implementor, "Implementor cannot be null");
    }
    
    /**
     * 抽象层的操作,由子类实现
     * 业务含义:对外暴露的统一接口
     */
    public abstract void operation();
    
    /**
     * 获取当前实现类型
     */
    public String getImplementorType() {
        return implementor.getType();
    }
}

// 扩展抽象类,实现具体的业务操作
public class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }
    
    @Override
    public void operation() {
        try {
            // 调用实现层的操作,实现桥接
            System.out.println("RefinedAbstraction: 准备调用实现层");
            implementor.operationImpl();
            System.out.println("RefinedAbstraction: 完成调用实现层");
        } catch (Exception e) {
            System.err.println("Abstraction operation failed: " + e.getMessage());
            throw new RuntimeException("抽象层操作失败", e);
        }
    }
}

6.2 企业级应用场景:消息推送系统

业务背景: 企业级消息推送系统需要支持多种消息类型(短信、邮件、推送通知)和多种推送平台(阿里云、腾讯云、华为云),通过桥接模式实现消息类型与推送平台的解耦。

package com.example.patterns.bridge.message;

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.time.LocalDateTime;

// 推送平台接口
public interface MessagePlatform {
    /**
     * 发送消息
     * @param recipient 接收者
     * @param content 消息内容
     * @param metadata 元数据
     * @return 推送结果
     */
    PushResult sendMessage(String recipient, String content, Map<String, Object> metadata);
    
    /**
     * 获取平台名称
     */
    String getPlatformName();
    
    /**
     * 检查平台状态
     */
    boolean isAvailable();
}

// 推送结果封装
public class PushResult {
    private boolean success;
    private String messageId;
    private String platformName;
    private String errorMessage;
    private LocalDateTime timestamp;
    
    public PushResult(boolean success, String messageId, String platformName, String errorMessage) {
        this.success = success;
        this.messageId = messageId;
        this.platformName = platformName;
        this.errorMessage = errorMessage;
        this.timestamp = LocalDateTime.now();
    }
    
    // Getter方法
    public boolean isSuccess() { return success; }
    public String getMessageId() { return messageId; }
    public String getPlatformName() { return platformName; }
    public String getErrorMessage() { return errorMessage; }
    public LocalDateTime getTimestamp() { return timestamp; }
    
    @Override
    public String toString() {
        return String.format("PushResult{success=%s, messageId='%s', platform='%s', error='%s', time=%s}", 
                success, messageId, platformName, errorMessage, timestamp);
    }
}

// 阿里云推送平台实现
public class AliyunMessagePlatform implements MessagePlatform {
    private boolean available = true;
    
    @Override
    public PushResult sendMessage(String recipient, String content, Map<String, Object> metadata) {
        try {
            if (!isAvailable()) {
                return new PushResult(false, null, getPlatformName(), "阿里云平台暂不可用");
            }
            
            // 模拟阿里云推送逻辑
            String messageId = "aliyun_" + System.currentTimeMillis();
            System.out.println("阿里云推送: 发送到 " + recipient + ", 内容: " + content);
            
            return new PushResult(true, messageId, getPlatformName(), null);
        } catch (Exception e) {
            return new PushResult(false, null, getPlatformName(), "阿里云推送异常: " + e.getMessage());
        }
    }
    
    @Override
    public String getPlatformName() {
        return "阿里云";
    }
    
    @Override
    public boolean isAvailable() {
        return available;
    }
    
    public void setAvailable(boolean available) {
        this.available = available;
    }
}

// 腾讯云推送平台实现
public class TencentMessagePlatform implements MessagePlatform {
    private boolean available = true;
    
    @Override
    public PushResult sendMessage(String recipient, String content, Map<String, Object> metadata) {
        try {
            if (!isAvailable()) {
                return new PushResult(false, null, getPlatformName(), "腾讯云平台暂不可用");
            }
            
            // 模拟腾讯云推送逻辑
            String messageId = "tencent_" + System.currentTimeMillis();
            System.out.println("腾讯云推送: 发送到 " + recipient + ", 内容: " + content);
            
            return new PushResult(true, messageId, getPlatformName(), null);
        } catch (Exception e) {
            return new PushResult(false, null, getPlatformName(), "腾讯云推送异常: " + e.getMessage());
        }
    }
    
    @Override
    public String getPlatformName() {
        return "腾讯云";
    }
    
    @Override
    public boolean isAvailable() {
        return available;
    }
    
    public void setAvailable(boolean available) {
        this.available = available;
    }
}

// 华为云推送平台实现
public class HuaweiMessagePlatform implements MessagePlatform {
    private boolean available = true;
    
    @Override
    public PushResult sendMessage(String recipient, String content, Map<String, Object> metadata) {
        try {
            if (!isAvailable()) {
                return new PushResult(false, null, getPlatformName(), "华为云平台暂不可用");
            }
            
            // 模拟华为云推送逻辑
            String messageId = "huawei_" + System.currentTimeMillis();
            System.out.println("华为云推送: 发送到 " + recipient + ", 内容: " + content);
            
            return new PushResult(true, messageId, getPlatformName(), null);
        } catch (Exception e) {
            return new PushResult(false, null, getPlatformName(), "华为云推送异常: " + e.getMessage());
        }
    }
    
    @Override
    public String getPlatformName() {
        return "华为云";
    }
    
    @Override
    public boolean isAvailable() {
        return available;
    }
    
    public void setAvailable(boolean available) {
        this.available = available;
    }
}

// 消息抽象类
public abstract class Message {
    protected final MessagePlatform platform;
    protected String title;
    protected String content;
    protected List<String> recipients;
    protected Map<String, Object> metadata;
    
    public Message(MessagePlatform platform) {
        this.platform = Objects.requireNonNull(platform, "MessagePlatform cannot be null");
        this.recipients = new ArrayList<>();
        this.metadata = new HashMap<>();
    }
    
    public Message setTitle(String title) {
        this.title = title;
        return this;
    }
    
    public Message setContent(String content) {
        this.content = content;
        return this;
    }
    
    public Message addRecipient(String recipient) {
        if (recipient != null && !recipient.trim().isEmpty()) {
            this.recipients.add(recipient);
        }
        return this;
    }
    
    public Message addMetadata(String key, Object value) {
        this.metadata.put(key, value);
        return this;
    }
    
    /**
     * 发送消息的抽象方法,由子类实现
     */
    public abstract List<PushResult> send();
    
    /**
     * 格式化消息内容,由子类实现
     */
    protected abstract String formatContent();
}

// 短信消息实现
public class SmsMessage extends Message {
    public SmsMessage(MessagePlatform platform) {
        super(platform);
    }
    
    @Override
    public List<PushResult> send() {
        List<PushResult> results = new ArrayList<>();
        String formattedContent = formatContent();
        
        for (String recipient : recipients) {
            try {
                PushResult result = platform.sendMessage(recipient, formattedContent, metadata);
                results.add(result);
            } catch (Exception e) {
                PushResult errorResult = new PushResult(false, null, platform.getPlatformName(), 
                    "发送短信异常: " + e.getMessage());
                results.add(errorResult);
            }
        }
        
        return results;
    }
    
    @Override
    protected String formatContent() {
        return "【短信通知】" + (title != null ? title + ": " : "") + content;
    }
}

// 邮件消息实现
public class EmailMessage extends Message {
    public EmailMessage(MessagePlatform platform) {
        super(platform);
    }
    
    @Override
    public List<PushResult> send() {
        List<PushResult> results = new ArrayList<>();
        String formattedContent = formatContent();
        
        for (String recipient : recipients) {
            try {
                // 邮件特有的元数据
                Map<String, Object> emailMetadata = new HashMap<>(metadata);
                emailMetadata.put("subject", title);
                emailMetadata.put("type", "email");
                
                PushResult result = platform.sendMessage(recipient, formattedContent, emailMetadata);
                results.add(result);
            } catch (Exception e) {
                PushResult errorResult = new PushResult(false, null, platform.getPlatformName(), 
                    "发送邮件异常: " + e.getMessage());
                results.add(errorResult);
            }
        }
        
        return results;
    }
    
    @Override
    protected String formatContent() {
        StringBuilder html = new StringBuilder();
        html.append("<html><body>");
        if (title != null) {
            html.append("<h2>").append(title).append("</h2>");
        }
        html.append("<p>").append(content).append("</p>");
        html.append("</body></html>");
        return html.toString();
    }
}

// 推送通知消息实现
public class PushNotification extends Message {
    public PushNotification(MessagePlatform platform) {
        super(platform);
    }
    
    @Override
    public List<PushResult> send() {
        List<PushResult> results = new ArrayList<>();
        String formattedContent = formatContent();
        
        for (String recipient : recipients) {
            try {
                // 推送通知特有的元数据
                Map<String, Object> pushMetadata = new HashMap<>(metadata);
                pushMetadata.put("title", title);
                pushMetadata.put("type", "push");
                pushMetadata.put("badge", 1);
                
                PushResult result = platform.sendMessage(recipient, formattedContent, pushMetadata);
                results.add(result);
            } catch (Exception e) {
                PushResult errorResult = new PushResult(false, null, platform.getPlatformName(), 
                    "发送推送通知异常: " + e.getMessage());
                results.add(errorResult);
            }
        }
        
        return results;
    }
    
    @Override
    protected String formatContent() {
        return content;
    }
}

// 消息工厂
public class MessageFactory {
    public static Message createSmsMessage(MessagePlatform platform) {
        return new SmsMessage(platform);
    }
    
    public static Message createEmailMessage(MessagePlatform platform) {
        return new EmailMessage(platform);
    }
    
    public static Message createPushNotification(MessagePlatform platform) {
        return new PushNotification(platform);
    }
}

// 平台工厂
public class PlatformFactory {
    public static MessagePlatform createAliyunPlatform() {
        return new AliyunMessagePlatform();
    }
    
    public static MessagePlatform createTencentPlatform() {
        return new TencentMessagePlatform();
    }
    
    public static MessagePlatform createHuaweiPlatform() {
        return new HuaweiMessagePlatform();
    }
}

6.3 绘图系统场景

业务背景: 跨平台绘图系统,支持多种形状和多种绘图API的组合。

package com.example.patterns.bridge.graphics;

import java.awt.Color;

// 绘图API接口
public interface DrawingAPI {
    void drawCircle(double x, double y, double radius, Color color);
    void drawRectangle(double x, double y, double width, double height, Color color);
    void drawLine(double x1, double y1, double x2, double y2, Color color);
    String getApiName();
}

// Windows绘图API实现
public class WindowsDrawingAPI implements DrawingAPI {
    @Override
    public void drawCircle(double x, double y, double radius, Color color) {
        System.out.printf("Windows API: 绘制圆形 at (%.1f,%.1f) radius=%.1f color=%s%n", 
                x, y, radius, color.toString());
    }
    
    @Override
    public void drawRectangle(double x, double y, double width, double height, Color color) {
        System.out.printf("Windows API: 绘制矩形 at (%.1f,%.1f) size=%.1fx%.1f color=%s%n", 
                x, y, width, height, color.toString());
    }
    
    @Override
    public void drawLine(double x1, double y1, double x2, double y2, Color color) {
        System.out.printf("Windows API: 绘制直线 from (%.1f,%.1f) to (%.1f,%.1f) color=%s%n", 
                x1, y1, x2, y2, color.toString());
    }
    
    @Override
    public String getApiName() {
        return "Windows GDI";
    }
}

// Linux绘图API实现
public class LinuxDrawingAPI implements DrawingAPI {
    @Override
    public void drawCircle(double x, double y, double radius, Color color) {
        System.out.printf("Linux X11: 绘制圆形 at (%.1f,%.1f) radius=%.1f color=%s%n", 
                x, y, radius, color.toString());
    }
    
    @Override
    public void drawRectangle(double x, double y, double width, double height, Color color) {
        System.out.printf("Linux X11: 绘制矩形 at (%.1f,%.1f) size=%.1fx%.1f color=%s%n", 
                x, y, width, height, color.toString());
    }
    
    @Override
    public void drawLine(double x1, double y1, double x2, double y2, Color color) {
        System.out.printf("Linux X11: 绘制直线 from (%.1f,%.1f) to (%.1f,%.1f) color=%s%n", 
                x1, y1, x2, y2, color.toString());
    }
    
    @Override
    public String getApiName() {
        return "Linux X11";
    }
}

// 形状抽象类
public abstract class Shape {
    protected final DrawingAPI drawingAPI;
    protected double x, y;
    protected Color color;
    
    public Shape(DrawingAPI drawingAPI, double x, double y, Color color) {
        this.drawingAPI = Objects.requireNonNull(drawingAPI, "DrawingAPI cannot be null");
        this.x = x;
        this.y = y;
        this.color = color != null ? color : Color.BLACK;
    }
    
    public abstract void draw();
    public abstract double getArea();
    
    public void move(double deltaX, double deltaY) {
        this.x += deltaX;
        this.y += deltaY;
    }
    
    public void setColor(Color color) {
        this.color = color != null ? color : Color.BLACK;
    }
    
    public String getApiName() {
        return drawingAPI.getApiName();
    }
}

// 圆形实现
public class Circle extends Shape {
    private double radius;
    
    public Circle(DrawingAPI drawingAPI, double x, double y, double radius, Color color) {
        super(drawingAPI, x, y, color);
        this.radius = Math.max(0, radius);
    }
    
    @Override
    public void draw() {
        drawingAPI.drawCircle(x, y, radius, color);
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    public void setRadius(double radius) {
        this.radius = Math.max(0, radius);
    }
    
    public double getRadius() {
        return radius;
    }
}

// 矩形实现
public class Rectangle extends Shape {
    private double width, height;
    
    public Rectangle(DrawingAPI drawingAPI, double x, double y, double width, double height, Color color) {
        super(drawingAPI, x, y, color);
        this.width = Math.max(0, width);
        this.height = Math.max(0, height);
    }
    
    @Override
    public void draw() {
        drawingAPI.drawRectangle(x, y, width, height, color);
    }
    
    @Override
    public double getArea() {
        return width * height;
    }
    
    public void setSize(double width, double height) {
        this.width = Math.max(0, width);
        this.height = Math.max(0, height);
    }
    
    public double getWidth() { return width; }
    public double getHeight() { return height; }
}

// 客户端使用示例
public class BridgeClient {
    public static void main(String[] args) {
        // 消息推送系统示例
        MessagePlatform aliyun = PlatformFactory.createAliyunPlatform();
        Message smsMessage = MessageFactory.createSmsMessage(aliyun)
                .setTitle("系统通知")
                .setContent("您有一条新消息")
                .addRecipient("13800138000")
                .addRecipient("13900139000");
        
        List<PushResult> results = smsMessage.send();
        results.forEach(System.out::println);
        
        // 绘图系统示例
        DrawingAPI windowsAPI = new WindowsDrawingAPI();
        DrawingAPI linuxAPI = new LinuxDrawingAPI();
        
        Shape circle1 = new Circle(windowsAPI, 10, 10, 5, Color.RED);
        Shape circle2 = new Circle(linuxAPI, 20, 20, 8, Color.BLUE);
        
        System.out.println("绘制图形:");
        circle1.draw();
        circle2.draw();
        
        System.out.printf("圆形1面积: %.2f (使用%s)%n", circle1.getArea(), circle1.getApiName());
        System.out.printf("圆形2面积: %.2f (使用%s)%n", circle2.getArea(), circle2.getApiName());
    }
    // 总结:通过桥接模式,消息类型与推送平台、形状与绘图API实现了解耦,便于灵活扩展和组合。
}

7. 测试用例

业务背景: 验证桥接模式的核心功能,包括基本桥接功能、消息推送系统和绘图系统。

package com.example.patterns.bridge.test;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.*;
import java.awt.Color;
import java.util.List;

public class BridgePatternTest {
    
    private MessagePlatform aliyunPlatform;
    private MessagePlatform tencentPlatform;
    private DrawingAPI windowsAPI;
    private DrawingAPI linuxAPI;
    
    @BeforeEach
    public void setUp() {
        aliyunPlatform = PlatformFactory.createAliyunPlatform();
        tencentPlatform = PlatformFactory.createTencentPlatform();
        windowsAPI = new WindowsDrawingAPI();
        linuxAPI = new LinuxDrawingAPI();
    }
    
    @Test
    public void testBasicBridgePattern() {
        // 测试基本桥接模式
        Implementor implA = new ConcreteImplementorA();
        Implementor implB = new ConcreteImplementorB();
        
        Abstraction abstractionA = new RefinedAbstraction(implA);
        Abstraction abstractionB = new RefinedAbstraction(implB);
        
        // 验证可以正常调用
        assertDoesNotThrow(() -> {
            abstractionA.operation();
            abstractionB.operation();
        });
        
        // 验证实现类型正确
        assertEquals("ImplementorA", abstractionA.getImplementorType());
        assertEquals("ImplementorB", abstractionB.getImplementorType());
    }
    
    @Test
    public void testAbstractionWithNullImplementor() {
        // 测试空实现异常处理
        assertThrows(NullPointerException.class, () -> {
            new RefinedAbstraction(null);
        });
    }
    
    @Test
    public void testSmsMessageSending() {
        // 测试短信消息发送
        Message smsMessage = MessageFactory.createSmsMessage(aliyunPlatform)
                .setTitle("测试通知")
                .setContent("这是一条测试短信")
                .addRecipient("13800138000")
                .addRecipient("13900139000");
        
        List<PushResult> results = smsMessage.send();
        
        assertNotNull("发送结果不应为空", results);
        assertEquals("应该有两条发送结果", 2, results.size());
        
        for (PushResult result : results) {
            assertTrue("发送应该成功", result.isSuccess());
            assertEquals("平台应为阿里云", "阿里云", result.getPlatformName());
            assertNotNull("消息ID不应为空", result.getMessageId());
            assertTrue("消息ID应以aliyun开头", result.getMessageId().startsWith("aliyun_"));
        }
    }
    
    @Test
    public void testEmailMessageSending() {
        // 测试邮件消息发送
        Message emailMessage = MessageFactory.createEmailMessage(tencentPlatform)
                .setTitle("重要通知")
                .setContent("这是一封重要邮件")
                .addRecipient("test@example.com")
                .addMetadata("priority", "high");
        
        List<PushResult> results = emailMessage.send();
        
        assertNotNull("发送结果不应为空", results);
        assertEquals("应该有一条发送结果", 1, results.size());
        
        PushResult result = results.get(0);
        assertTrue("发送应该成功", result.isSuccess());
        assertEquals("平台应为腾讯云", "腾讯云", result.getPlatformName());
        assertNotNull("时间戳不应为空", result.getTimestamp());
    }
    
    @Test
    public void testPushNotificationSending() {
        // 测试推送通知发送
        MessagePlatform huaweiPlatform = PlatformFactory.createHuaweiPlatform();
        Message pushMessage = MessageFactory.createPushNotification(huaweiPlatform)
                .setTitle("系统更新")
                .setContent("新版本已可用")
                .addRecipient("user123")
                .addMetadata("action", "update");
        
        List<PushResult> results = pushMessage.send();
        
        assertNotNull("发送结果不应为空", results);
        assertEquals("应该有一条发送结果", 1, results.size());
        
        PushResult result = results.get(0);
        assertTrue("发送应该成功", result.isSuccess());
        assertEquals("平台应为华为云", "华为云", result.getPlatformName());
        assertTrue("消息ID应以huawei开头", result.getMessageId().startsWith("huawei_"));
    }
    
    @Test
    public void testMessageWithUnavailablePlatform() {
        // 测试平台不可用时的处理
        AliyunMessagePlatform aliyun = new AliyunMessagePlatform();
        aliyun.setAvailable(false);
        
        Message smsMessage = MessageFactory.createSmsMessage(aliyun)
                .setContent("测试消息")
                .addRecipient("13800138000");
        
        List<PushResult> results = smsMessage.send();
        
        assertNotNull("发送结果不应为空", results);
        assertEquals("应该有一条发送结果", 1, results.size());
        
        PushResult result = results.get(0);
        assertFalse("发送应该失败", result.isSuccess());
        assertEquals("错误信息应正确", "阿里云平台暂不可用", result.getErrorMessage());
    }
    
    @Test
    public void testMessageWithNullPlatform() {
        // 测试空平台异常处理
        assertThrows(NullPointerException.class, () -> {
            MessageFactory.createSmsMessage(null);
        });
    }
    
    @Test
    public void testMessageBuilderPattern() {
        // 测试消息构建器模式
        Message message = MessageFactory.createSmsMessage(aliyunPlatform)
                .setTitle("测试")
                .setContent("内容")
                .addRecipient("13800138000")
                .addRecipient("") // 空接收者应被忽略
                .addRecipient(null) // null接收者应被忽略
                .addMetadata("key1", "value1")
                .addMetadata("key2", "value2");
        
        List<PushResult> results = message.send();
        
        // 应该只有一条有效的接收者
        assertEquals("应该只有一条发送结果", 1, results.size());
    }
    
    @Test
    public void testCircleDrawing() {
        // 测试圆形绘制
        Shape circle1 = new Circle(windowsAPI, 10, 10, 5, Color.RED);
        Shape circle2 = new Circle(linuxAPI, 20, 20, 8, Color.BLUE);
        
        // 验证可以正常绘制
        assertDoesNotThrow(() -> {
            circle1.draw();
            circle2.draw();
        });
        
        // 验证API名称
        assertEquals("Windows GDI", circle1.getApiName());
        assertEquals("Linux X11", circle2.getApiName());
        
        // 验证面积计算
        assertEquals(Math.PI * 25, circle1.getArea(), 0.001);
        assertEquals(Math.PI * 64, circle2.getArea(), 0.001);
    }
    
    @Test
    public void testRectangleDrawing() {
        // 测试矩形绘制
        Shape rect1 = new Rectangle(windowsAPI, 0, 0, 10, 20, Color.GREEN);
        Shape rect2 = new Rectangle(linuxAPI, 5, 5, 15, 25, Color.YELLOW);
        
        // 验证可以正常绘制
        assertDoesNotThrow(() -> {
            rect1.draw();
            rect2.draw();
        });
        
        // 验证面积计算
        assertEquals(200, rect1.getArea(), 0.001);
        assertEquals(375, rect2.getArea(), 0.001);
    }
    
    @Test
    public void testShapeWithNullAPI() {
        // 测试空绘图API异常处理
        assertThrows(NullPointerException.class, () -> {
            new Circle(null, 0, 0, 5, Color.RED);
        });
        
        assertThrows(NullPointerException.class, () -> {
            new Rectangle(null, 0, 0, 10, 20, Color.BLUE);
        });
    }
    
    @Test
    public void testShapeMovement() {
        // 测试形状移动
        Circle circle = new Circle(windowsAPI, 10, 10, 5, Color.RED);
        
        circle.move(5, 3);
        
        // 注意:这里我们无法直接验证移动结果,因为x,y是protected
        // 在实际项目中,可以添加getter方法或测试绘制输出
        assertDoesNotThrow(() -> circle.draw());
    }
    
    @Test
    public void testShapeColorChange() {
        // 测试形状颜色变更
        Circle circle = new Circle(windowsAPI, 10, 10, 5, Color.RED);
        
        circle.setColor(Color.BLUE);
        circle.setColor(null); // 应设置为默认黑色
        
        assertDoesNotThrow(() -> circle.draw());
    }
    
    @Test
    public void testCircleRadiusValidation() {
        // 测试圆形半径验证
        Circle circle = new Circle(windowsAPI, 0, 0, -5, Color.RED);
        
        // 负半径应被修正为0
        assertEquals(0, circle.getRadius(), 0.001);
        
        circle.setRadius(10);
        assertEquals(10, circle.getRadius(), 0.001);
        
        circle.setRadius(-3); // 应被修正为0
        assertEquals(0, circle.getRadius(), 0.001);
    }
    
    @Test
    public void testRectangleSizeValidation() {
        // 测试矩形尺寸验证
        Rectangle rect = new Rectangle(windowsAPI, 0, 0, -10, -20, Color.BLUE);
        
        // 负尺寸应被修正为0
        assertEquals(0, rect.getWidth(), 0.001);
        assertEquals(0, rect.getHeight(), 0.001);
        assertEquals(0, rect.getArea(), 0.001);
        
        rect.setSize(15, 25);
        assertEquals(15, rect.getWidth(), 0.001);
        assertEquals(25, rect.getHeight(), 0.001);
        assertEquals(375, rect.getArea(), 0.001);
    }
    
    @Test
    public void testMessageFactoryCreation() {
        // 测试消息工厂创建
        Message sms = MessageFactory.createSmsMessage(aliyunPlatform);
        Message email = MessageFactory.createEmailMessage(aliyunPlatform);
        Message push = MessageFactory.createPushNotification(aliyunPlatform);
        
        assertTrue("应创建短信消息", sms instanceof SmsMessage);
        assertTrue("应创建邮件消息", email instanceof EmailMessage);
        assertTrue("应创建推送通知", push instanceof PushNotification);
    }
    
    @Test
    public void testPlatformFactoryCreation() {
        // 测试平台工厂创建
        MessagePlatform aliyun = PlatformFactory.createAliyunPlatform();
        MessagePlatform tencent = PlatformFactory.createTencentPlatform();
        MessagePlatform huawei = PlatformFactory.createHuaweiPlatform();
        
        assertTrue("应创建阿里云平台", aliyun instanceof AliyunMessagePlatform);
        assertTrue("应创建腾讯云平台", tencent instanceof TencentMessagePlatform);
        assertTrue("应创建华为云平台", huawei instanceof HuaweiMessagePlatform);
        
        assertEquals("阿里云", aliyun.getPlatformName());
        assertEquals("腾讯云", tencent.getPlatformName());
        assertEquals("华为云", huawei.getPlatformName());
    }
    
    @Test
    public void testPushResultToString() {
        // 测试推送结果字符串表示
        PushResult result = new PushResult(true, "test123", "阿里云", null);
        
        String resultString = result.toString();
        assertNotNull("字符串表示不应为空", resultString);
        assertTrue("应包含成功状态", resultString.contains("success=true"));
        assertTrue("应包含消息ID", resultString.contains("messageId='test123'"));
        assertTrue("应包含平台名称", resultString.contains("platform='阿里云'"));
    }
}

8. 常见误区与反例

8.1 常见误区

  • 误区1 :过度使用桥接模式

    // 错误示例:为简单功能滥用桥接模式
    public interface SimpleOperation {
        void doSomething();
    }
    
    public class SimpleImplementation implements SimpleOperation {
        public void doSomething() { System.out.println("简单操作"); }
    }
    
    // 不必要的抽象层
    public abstract class UnnecessaryAbstraction {
        protected SimpleOperation operation;
        public UnnecessaryAbstraction(SimpleOperation operation) {
            this.operation = operation;
        }
        public abstract void execute();
    }
    

    正确做法:只在真正需要多维度扩展时使用桥接模式。

  • 误区2 :抽象与实现边界不清

    // 错误示例:抽象层包含具体实现逻辑
    public class BadAbstraction {
        private Implementation impl;
        
        public void operation() {
            // 错误:在抽象层处理具体业务逻辑
            validateInput();
            logOperation();
            impl.doWork();
            updateDatabase();
        }
    }
    

    正确做法:抽象层只做接口转换,具体逻辑放在实现层。

  • 误区3 :忽略运行时切换的线程安全

    // 错误示例:非线程安全的实现切换
    public class UnsafeAbstraction {
        private Implementation impl;
        
        public void setImplementation(Implementation impl) {
            this.impl = impl; // 可能导致并发问题
        }
    }
    

8.2 反例分析

  • 反例1 :硬编码实现选择
    在抽象层中硬编码选择具体实现,失去了桥接模式的灵活性。

  • 反例2 :实现层相互依赖
    不同实现之间存在耦合,违反了桥接模式的解耦原则。

  • 反例3 :抽象层过于复杂
    抽象层包含过多业务逻辑,模糊了抽象与实现的边界。

9. 最佳实践

9.1 设计原则

  1. 清晰的职责分离 :明确抽象和实现的边界

    // 推荐:清晰的职责分离
    public abstract class PaymentProcessor {
        protected final PaymentGateway gateway;
        
        public PaymentProcessor(PaymentGateway gateway) {
            this.gateway = Objects.requireNonNull(gateway);
        }
        
        // 抽象层负责流程控制
        public final PaymentResult process(PaymentRequest request) {
            validateRequest(request);
            return doProcess(request);
        }
        
        protected abstract PaymentResult doProcess(PaymentRequest request);
        protected abstract void validateRequest(PaymentRequest request);
    }
    
  2. 接口设计要稳定 :实现接口应保持向后兼容

    // 推荐:版本化接口设计
    public interface PaymentGateway {
        PaymentResult processPayment(PaymentRequest request);
        
        // 扩展方法,保持向后兼容
        default PaymentResult processPayment(PaymentRequest request, PaymentOptions options) {
            return processPayment(request);
        }
        
        String getGatewayVersion();
    }
    

9.2 实现技巧

  1. 使用工厂模式创建桥接 :简化客户端使用

    // 推荐:桥接工厂
    public class MessageBridgeFactory {
        private static final Map<String, MessagePlatform> PLATFORMS = new ConcurrentHashMap<>();
        
        static {
            PLATFORMS.put("aliyun", new AliyunMessagePlatform());
            PLATFORMS.put("tencent", new TencentMessagePlatform());
            PLATFORMS.put("huawei", new HuaweiMessagePlatform());
        }
        
        public static Message createMessage(String type, String platform) {
            MessagePlatform platformImpl = PLATFORMS.get(platform);
            if (platformImpl == null) {
                throw new IllegalArgumentException("Unsupported platform: " + platform);
            }
            
            return MessageFactory.createMessage(type, platformImpl);
        }
    }
    
  2. 支持运行时切换 :提供安全的实现切换机制

    // 推荐:线程安全的实现切换
    public class SwitchableProcessor {
        private volatile Implementation impl;
        private final ReadWriteLock lock = new ReentrantReadWriteLock();
        
        public void switchImplementation(Implementation newImpl) {
            lock.writeLock().lock();
            try {
                this.impl = Objects.requireNonNull(newImpl);
            } finally {
                lock.writeLock().unlock();
            }
        }
        
        public void process() {
            lock.readLock().lock();
            try {
                impl.doWork();
            } finally {
                lock.readLock().unlock();
            }
        }
    }
    
  3. 配置化实现选择 :通过配置管理实现选择

    // 推荐:配置化桥接
    @Component
    public class ConfigurableBridge {
        @Value("${bridge.implementation.type:default}")
        private String implementationType;
        
        @Autowired
        private Map<String, Implementation> implementations;
        
        @PostConstruct
        public void init() {
            Implementation impl = implementations.get(implementationType);
            if (impl == null) {
                throw new IllegalStateException("No implementation found for type: " + implementationType);
            }
            setImplementation(impl);
        }
    }
    

9.3 性能优化

  1. 缓存策略 :合理使用缓存提升性能

    // 推荐:带缓存的桥接实现
    public class CachedMessageBridge {
        private final MessagePlatform platform;
        private final Cache<String, MessageTemplate> templateCache;
        
        public CachedMessageBridge(MessagePlatform platform) {
            this.platform = platform;
            this.templateCache = Caffeine.newBuilder()
                    .maximumSize(1000)
                    .expireAfterWrite(Duration.ofMinutes(30))
                    .build();
        }
        
        public PushResult sendTemplateMessage(String templateId, Map<String, Object> params) {
            MessageTemplate template = templateCache.get(templateId, 
                key -> platform.getTemplate(key));
            return platform.sendMessage(template.format(params));
        }
    }
    
  2. 异步处理 :支持异步操作提升吞吐量

    // 推荐:异步桥接实现
    public class AsyncMessageBridge {
        private final MessagePlatform platform;
        private final Executor executor;
        
        public CompletableFuture<PushResult> sendMessageAsync(Message message) {
            return CompletableFuture.supplyAsync(() -> {
                try {
                    return platform.sendMessage(message);
                } catch (Exception e) {
                    return new PushResult(false, null, platform.getPlatformName(), e.getMessage());
                }
            }, executor);
        }
    }
    

9.4 架构考虑

  1. 监控和日志 :完善的观察性支持

    // 推荐:带监控的桥接实现
    public class MonitoredBridge {
        private static final Logger log = LoggerFactory.getLogger(MonitoredBridge.class);
        private final MeterRegistry meterRegistry;
        private final Implementation impl;
        
        public void process(Request request) {
            Timer.Sample sample = Timer.start(meterRegistry);
            String implType = impl.getClass().getSimpleName();
            
            try {
                log.debug("Processing request with implementation: {}", implType);
                impl.doWork(request);
                meterRegistry.counter("bridge.success", "impl", implType).increment();
            } catch (Exception e) {
                log.error("Bridge processing failed with implementation: {}", implType, e);
                meterRegistry.counter("bridge.error", "impl", implType).increment();
                throw e;
            } finally {
                sample.stop(Timer.builder("bridge.duration")
                        .tag("impl", implType)
                        .register(meterRegistry));
            }
        }
    }
    
  2. 扩展点设计 :提供灵活的扩展机制

    // 推荐:可扩展的桥接设计
    public abstract class ExtensibleBridge {
        protected final List<BridgeInterceptor> interceptors = new ArrayList<>();
        protected final Implementation impl;
        
        public void addInterceptor(BridgeInterceptor interceptor) {
            interceptors.add(interceptor);
        }
        
        protected final void process(Request request) {
            // 前置处理
            interceptors.forEach(i -> i.beforeProcess(request));
            
            try {
                doProcess(request);
                // 后置处理
                interceptors.forEach(i -> i.afterProcess(request));
            } catch (Exception e) {
                // 异常处理
                interceptors.forEach(i -> i.onError(request, e));
                throw e;
            }
        }
        
        protected abstract void doProcess(Request request);
    }
    
  3. 版本兼容性 :支持多版本实现共存

    // 推荐:版本感知的桥接
    public class VersionAwareBridge {
        private final Map<String, Implementation> implementations;
        
        public void process(Request request) {
            String version = request.getVersion();
            Implementation impl = implementations.get(version);
            
            if (impl == null) {
                // 降级到默认版本
                impl = implementations.get("default");
            }
            
            if (impl == null) {
                throw new UnsupportedOperationException("No implementation for version: " + version);
            }
            
            impl.process(request);
        }
    }
    

10. 参考资料与延伸阅读

  • 《设计模式:可复用面向对象软件的基础》GoF
  • Effective Java(中文版)
  • https://refactoringguru.cn/design-patterns/bridge
  • https://www.baeldung.com/java-bridge-pattern

本文为设计模式系列第10篇,后续每篇将聚焦一个设计模式或设计原则,深入讲解实现与应用,敬请关注。