
每个多渠道支付系统都以同样的方式开始一个 PaymentService 加一个巨大的 switch 语句。支付宝调 alipayClient.pay()。微信调 wechatClient.pay()。银联调 unionPayClient.pay()。银行转账那完全是另一种流程。每个渠道有自己的请求格式、自己的错误处理、自己的幂等机制。代码长成怪物。不是因为业务逻辑复杂——每次都是三步创建订单、调渠道、处理结果。复杂来自耦合每次加渠道你改 PaymentService。每次渠道改 API 你改 PaymentService。每次加功能日志、重试、回调你改每个 if-else 分支。桥接模式把系统拆成两个层级抽象层级你做什么和实现层级你怎么做。抽象层级定义支付流程。实现层级定义渠道特定行为。它们独立演化。加渠道意味着在实现层级加一个类。加功能意味着修改抽象层级。任一变更不触碰另一个。if-else 支付怪兽这是大多数支付服务几年后的样子java Service public class PaymentService {public PaymentResult pay(PaymentRequest request) { String channel request.getChannel(); if (alipay.equals(channel)) { AlipayRequest alipayReq new AlipayRequest(); alipayReq.setOutTradeNo(request.getOrderId()); alipayReq.setTotalAmount(request.getAmount().toString()); AlipayResponse resp alipayClient.tradePay(alipayReq); if (resp.isSuccess()) { return PaymentResult.success(resp.getTradeNo()); } else { return PaymentResult.fail(resp.getSubCode(), resp.getSubMsg()); } } else if (wechat.equals(channel)) { WechatPayRequest wechatReq new WechatPayRequest(); WechatPayResponse resp wechatClient.pay(wechatReq); } else if (unionpay.equals(channel)) { // 银联完全不同 } throw new UnsupportedChannelException(channel); }} 问题不是 if-else 本身——而是每个分支包含完全不同的代码。请求构建、API 调用、错误处理、幂等——全部因渠道而异全部活在同一个方法里。这是最糟糕的耦合抽象支付流程和实现渠道细节融合在一起。桥接模式把它们分开。桥接模式两个层级的解法桥接模式定义两个独立层级通过一个引用连接 Abstraction (PaymentProcess) ├── RefinedAbstraction (StandardPaymentProcess) ├── RefinedAbstraction (RetryablePaymentProcess)Implementation (PaymentChannel) ├── ConcreteImpl (AlipayChannel) ├── ConcreteImpl (WechatChannel) ├── ConcreteImpl (UnionPayChannel) java // 实现层级渠道特定行为 public interface PaymentChannel { ChannelRequest buildRequest(PaymentOrder order); ChannelResponse callChannel(ChannelRequest request); PaymentResult parseResponse(ChannelResponse response); boolean supports(String channelCode); }// 抽象层级支付流程 public abstract class PaymentProcess { protected PaymentChannel channel;public PaymentProcess(PaymentChannel channel) { this.channel channel; } public PaymentResult process(PaymentOrder order) { ChannelRequest request channel.buildRequest(order); ChannelResponse response channel.callChannel(request); PaymentResult result channel.parseResponse(response); return result; }}// 细化抽象加重试 public class RetryablePaymentProcess extends PaymentProcess { private final int maxRetries;Override public PaymentResult process(PaymentOrder order) { for (int i 0; i maxRetries; i) { PaymentResult result super.process(order); if (result.isSuccess() || !result.isRetryable()) { return result; } } return PaymentResult.fail(MAX_RETRIES_EXCEEDED); }} 两个层级独立演化加渠道不改 PaymentProcess加重试不改 PaymentChannel改支付宝 API 不改其他渠道。JDBC桥接模式的教科书案例JDBC 是桥接模式最纯粹的形式java Connection conn DriverManager.getConnection(url); PreparedStatement ps conn.prepareStatement(SELECT * FROM users); ResultSet rs ps.executeQuery();// 实现MySQL ConnectionImpl / PostgreSQL PgConnection / OracleConnection java.sql.Connection 是抽象定义数据库操作接口。MySQL/PostgreSQL/Oracle 的驱动是实现处理各自特定协议。你换数据库就换驱动实现层级。你换 JDBC 功能就升级 JDK抽象层级。任一变更不碰另一个。Spring AbstractRoutingDataSource桥接 策略Spring 的 AbstractRoutingDataSource 是桥接结合策略做实现选择java public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {private MapObject, DataSource resolvedDataSources; Override public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); } protected DataSource determineTargetDataSource() { Object lookupKey determineCurrentLookupKey(); DataSource ds resolvedDataSources.get(lookupKey); return ds ! null ? ds : resolvedDefaultDataSource; } protected abstract Object determineCurrentLookupKey();} 桥接引用不是静态的——基于 Context 动态选择。抽象控制流程委托给 Context 要求的实现。桥接什么时候比策略更合适策略模式实现每次调用都变基于当前 Context 选策略策略是可互换替代品。java PaymentStrategy strategy selector.select(order); strategy.pay(order);桥接模式实现是稳定的变异维度抽象和实现都是独立演化的层级桥接引用设置一次不随调用变化。java PaymentProcess process new RetryablePaymentProcess(new AlipayChannel()); process.process(order1); process.process(order2); // 同渠道不同订单支付系统通常是桥接不是策略因为抽象有变体标准、可重试、异步实现有变体支付宝、微信、银联两个维度独立演化。桥接模式的工程陷阱陷阱1实现接口膨胀实现接口长到包含两个层级需要的所有功能变成上帝接口。修复拆成核心 可选能力RetryableChannel, AsyncChannel抽象使用前检查 instanceof。陷阱2桥接引用泄漏外部代码直接访问实现抽象对流程的控制就丢了。修复不暴露实现引用给抽象加委托方法。陷阱3实现选择硬编码如果抽象总是创建同一个实现桥接就没意义。这是伪装成桥接的策略。选择应该发生在抽象外面——通过注入、配置或工厂。桥接不是策略的别名桥接是两个层级的独立演化。策略是每次调用的实现选择。支付渠道、数据库驱动、日志后端、消息协议——这些都是桥接候选因为抽象和实现都是真实层级有自己的演化时间线。如果你一直叫这些策略用 Map 查找来建它们你用了错误的模式。Map 是扁平选择器。桥接需要两个层级。你的系统有它们——你只是从来没给它们分开的接口。对了我在做的那个小程序「爪爪代码冒险记」里桥接模式用卡皮巴拉走两条吊桥过河来类比——抽象桥和实现桥各自延伸中间对接。比纯看代码直观搜搜看。