• 设计模式-06-桥接模式


           经典的设计模式有23种,但是常用的设计模式一般情况下不会到一半,我们就针对一些常用的设计模式进行一些详细的讲解和分析,方便大家更加容易理解和使用设计模式。

    1-什么是桥接模式

           桥接模式,也叫作桥梁模式,英文是Bridge Design Pattern。在GoF的《设计模式》一书中,桥接模式是这么定义的:"Decouple an abstraction from its implementation so that the two can vary independently。"翻译成中文就是:"将抽象和实现解耦,让它们可以独立变化。"

           另外一种理解方式:“一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。”通过组合关系来替代继承关系,避免继承层次的指数级爆炸。这种理解方式非常类似于,我们之前讲过的“组合优于继承”设计原则。

    2-桥接模式示例

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

    1. public enum NotificationEmergencyLevel {
    2. SEVERE, URGENCY, NORMAL, TRIVIAL
    3. }
    4. public class Notification {
    5. private List emailAddresses;
    6. private List telephones;
    7. private List wechatIds;
    8. public Notification() {}
    9. public void setEmailAddress(List emailAddress) {
    10. this.emailAddresses = emailAddress;
    11. }
    12. public void setTelephones(List telephones) {
    13. this.telephones = telephones;
    14. }
    15. public void setWechatIds(List wechatIds) {
    16. this.wechatIds = wechatIds;
    17. }
    18. public void notify(NotificationEmergencyLevel level, String message) {
    19. if (level.equals(NotificationEmergencyLevel.SEVERE)) {
    20. //...自动语音电话
    21. } else if (level.equals(NotificationEmergencyLevel.URGENCY)) {
    22. //...发微信
    23. } else if (level.equals(NotificationEmergencyLevel.NORMAL)) {
    24. //...发邮件
    25. } else if (level.equals(NotificationEmergencyLevel.TRIVIAL)) {
    26. //...发邮件
    27. }
    28. }
    29. }
    30. //在API监控告警的例子中,我们如下方式来使用Notification类:
    31. public class ErrorAlertHandler extends AlertHandler {
    32. public ErrorAlertHandler(AlertRule rule, Notification notification){
    33. super(rule, notification);
    34. }
    35. @Override
    36. public void check(ApiStatInfo apiStatInfo) {
    37. if (apiStatInfo.getErrorCount() > rule.getMatchedRule(apiStatInfo.getApi()).getMaxErrorCount()) {
    38. notification.notify(NotificationEmergencyLevel.SEVERE, "...");
    39. }
    40. }
    41. }

           Notification类的代码实现有一个最明显的问题,那就是有很多if-else分支逻辑。实际上,如果每个分支中的代码都不复杂,后期也没有无限膨胀的可能(增加更多if-else分支判断),那这样的设计问题并不大,没必要非得一定要摒弃if-else分支逻辑。

           不过,Notification的代码显然不符合这个条件。因为每个if-else分支中的代码逻辑都比较复杂,发送通知的所有逻辑都扎堆在Notification类中。我们知道,类的代码越多,就越难读懂,越难修改,维护的成本也就越高。很多设计模式都是试图将庞大的类拆分成更细小的类,然后再通过某种更合理的结构组装在一起。

            针对Notification的代码,我们将不同渠道的发送逻辑剥离出来,形成独立的消息发送类(MsgSender相关类)。其中,Notification类相当于抽象,MsgSender类相当于实现,两者可以独立开发,通过组合关系(也就是桥梁)任意组合在一起。所谓任意组合的意思就是,不同紧急程度的消息和发送渠道之间的对应关系,不是在代码中固定写死的,我们可以动态地去指定(比如,通过读取配置来获取对应关系)。

    1. public interface MsgSender {
    2. void send(String message);
    3. }
    4. public class TelephoneMsgSender implements MsgSender {
    5. private List telephones;
    6. public TelephoneMsgSender(List telephones) {
    7. this.telephones = telephones;
    8. }
    9. @Override
    10. public void send(String message) {
    11. //...
    12. }
    13. }
    14. public class EmailMsgSender implements MsgSender {
    15. // 与TelephoneMsgSender代码结构类似,所以省略...
    16. }
    17. public class WechatMsgSender implements MsgSender {
    18. // 与TelephoneMsgSender代码结构类似,所以省略...
    19. }
    20. public abstract class Notification {
    21. protected MsgSender msgSender;
    22. public Notification(MsgSender msgSender) {
    23. this.msgSender = msgSender;
    24. }
    25. public abstract void notify(String message);
    26. }
    27. public class SevereNotification extends Notification {
    28. public SevereNotification(MsgSender msgSender) {
    29. super(msgSender);
    30. }
    31. @Override
    32. public void notify(String message) {
    33. msgSender.send(message);
    34. }
    35. }
    36. public class UrgencyNotification extends Notification {
    37. // 与SevereNotification代码结构类似,所以省略...
    38. }
    39. public class NormalNotification extends Notification {
    40. // 与SevereNotification代码结构类似,所以省略...
    41. }
    42. public class TrivialNotification extends Notification {
    43. // 与SevereNotif

    3-小结

           对于第一种GoF的理解方式,弄懂定义中“抽象”和“实现”两个概念,是理解它的关键。定义中的“抽象”,指的并非“抽象类”或“接口”,而是被抽象出来的一套“类库”,它只包含骨架代码,真正的业务逻辑需要委派给定义中的“实现”来完成。而定义中的“实现”,也并非“接口的实现类”,而是的一套独立的“类库”。“抽象”和“实现”独立开发,通过对象之间的组合关系,组装在一起。

           对于第二种理解方式,它非常类似我们之前讲过的“组合优于继承”设计原则,通过组合关系来替代继承关系,避免继承层次的指数级爆炸。

  • 相关阅读:
    常用排序算法总结对比
    java返回前端树形结构数据(2种实现方式)
    聚苯乙烯修饰表面功能化CdSe/ZnS荧光量子点微球/硒化镉量子点聚苯乙烯磁微球性能
    实验4 NoSQL和关系数据库的操作比较
    Pillow(PIL)库的主要方法介绍
    java-net-php-python-ssm巴音学院本科部校园网站计算机毕业设计程序
    Springboot项目升级2.2.x升至2.7.x
    计算机操作系统 (第四版 汤小丹)(持续学习中)
    2022爱分析・采购数字化厂商全景报告 | 爱分析报告
    JavaScript基础
  • 原文地址:https://blog.csdn.net/ycmy2017/article/details/134399735