桥接模式(Bridge Design Pattern)

Decouple an abstraction from its implementation so that the two can vary independently.
将抽象和实现解耦,让它们可以独立变化。


关于桥接模式,很多书籍、资料中,还给出了更具体的理解方式:“一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。”通过组合关系来替代继承关系,避免继承层次的指数级爆炸。这种理解方式非常类似于,我们之前讲过的“组合优于继承”设计原则。

  • 个人理解

在我看来,这里的桥接的落地方式就是组合。核心思想就是将大的、耦合度高的类通过抽象为接口等手段合理拆分为小的类,再通过组合等方式将其更合理的拼装到一起,实现解耦。

How

示例

根据不同的告警规则,触发不同类型的告警。告警支持多种通知渠道,包括:邮件、短信、微信、自动语音电话。通知的紧急程度有多种类型,包括:SEVERE(严重)、URGENCY(紧急)、NORMAL(普通)、TRIVIAL(无关紧要)。不同的紧急程度对应不同的通知渠道。比如,SERVE(严重)级别的消息会通过“自动语音电话”告知相关人员。

  • 最简单的实现方式 ```java public enum NotificationEmergencyLevel { SEVERE, URGENCY, NORMAL, TRIVIAL }

public class Notification { private List emailAddresses; private List telephones; private List wechatIds;

public Notification() {}

public void setEmailAddress(List emailAddress) { this.emailAddresses = emailAddress; }

public void setTelephones(List telephones) { this.telephones = telephones; }

public void setWechatIds(List wechatIds) { this.wechatIds = wechatIds; }

public void notify(NotificationEmergencyLevel level, String message) { if (level.equals(NotificationEmergencyLevel.SEVERE)) { //…自动语音电话 } else if (level.equals(NotificationEmergencyLevel.URGENCY)) { //…发微信 } else if (level.equals(NotificationEmergencyLevel.NORMAL)) { //…发邮件 } else if (level.equals(NotificationEmergencyLevel.TRIVIAL)) { //…发邮件 } } }

//在API监控告警的例子中,我们如下方式来使用Notification类: public class ErrorAlertHandler extends AlertHandler { public ErrorAlertHandler(AlertRule rule, Notification notification){ super(rule, notification); }

@Override public void check(ApiStatInfo apiStatInfo) { if (apiStatInfo.getErrorCount() > rule.getMatchedRule(apiStatInfo.getApi()).getMaxErrorCount()) { notification.notify(NotificationEmergencyLevel.SEVERE, “…”); } } }

  1. - 问题分析:
  2. Notification 类的代码实现有一个最明显的问题,那就是有很多 if-else 分支逻辑。实际上,如果每个分支中的代码都不复杂,后期也没有无限膨胀的可能(增加更多 if-else 分支判断),那这样的设计问题并不大,没必要非得一定要摒弃 if-else 分支逻辑。不过,Notification 的代码显然不符合这个条件。因为每个 if-else 分支中的代码逻辑都比较复杂,发送通知的所有逻辑都扎堆在 Notification 类中。我们知道,类的代码越多,就越难读懂,越难修改,维护的成本也就越高。<br />很多设计模式都是试图将庞大的类拆分成更细小的类,然后再通过某种更合理的结构组装在一起。针对 Notification 的代码,我们将不同渠道的发送逻辑剥离出来,形成独立的消息发送类(MsgSender 相关类)。其中,Notification 类相当于抽象,MsgSender 类相当于实现,两者可以独立开发,通过组合关系(也就是桥梁)任意组合在一起。所谓任意组合的意思就是,不同紧急程度的消息和发送渠道之间的对应关系,不是在代码中固定写死的,我们可以动态地去指定(比如,通过读取配置来获取对应关系)。
  3. - **使用桥接模式重构**
  4. ```java
  5. public interface MsgSender {
  6. void send(String message);
  7. }
  8. public class TelephoneMsgSender implements MsgSender {
  9. private List<String> telephones;
  10. public TelephoneMsgSender(List<String> telephones) {
  11. this.telephones = telephones;
  12. }
  13. @Override
  14. public void send(String message) {
  15. //...
  16. }
  17. }
  18. public class EmailMsgSender implements MsgSender {
  19. // 与TelephoneMsgSender代码结构类似,所以省略...
  20. }
  21. public class WechatMsgSender implements MsgSender {
  22. // 与TelephoneMsgSender代码结构类似,所以省略...
  23. }
  24. public abstract class Notification {
  25. protected MsgSender msgSender;
  26. public Notification(MsgSender msgSender) {
  27. this.msgSender = msgSender;
  28. }
  29. public abstract void notify(String message);
  30. }
  31. public class SevereNotification extends Notification {
  32. public SevereNotification(MsgSender msgSender) {
  33. super(msgSender);
  34. }
  35. @Override
  36. public void notify(String message) {
  37. msgSender.send(message);
  38. }
  39. }
  40. public class UrgencyNotification extends Notification {
  41. // 与SevereNotification代码结构类似,所以省略...
  42. }
  43. public class NormalNotification extends Notification {
  44. // 与SevereNotification代码结构类似,所以省略...
  45. }
  46. public class TrivialNotification extends Notification {
  47. // 与SevereNotification代码结构类似,所以省略...
  48. }

经典应用

JDBC驱动