设计模式之桥接模式

定义

将抽象部分和它的实现部分分离,使它们都可以独立地变化。在现实生活中,某些类有两个或多个维度的变化,
如图形既可以按形状分,又可以按颜色分,如何画不同形状不同颜色的图形呢,如果用继承方式,m 种形状 n 种颜色的图形就有 m * n 种,
不但对应的子类很多,而且扩展困难,桥接模式就能很好的解决这些问题。

结构

  • Abstraction,抽象部分接口,持有一个实现部分的对象。
  • RefinedAbstraction,扩展抽象部分的对象,调用实现部分的对象来实现具体的业务方法。
  • Implementor,实现部分接口,定义自己的方法供抽象部分调用。
  • ConcreteImplementor,具体的实现部分对象。

简单实现

抽象部分接口

public abstract class Abstraction {

  protected Implementor implementor;

  public Abstraction(Implementor implementor) {
    this.implementor = implementor;
  }

  abstract void operation();
}

扩展抽象部分

public class RefinedAbstraction extends Abstraction {

  public RefinedAbstraction(Implementor implementor) {
    super(implementor);
  }

  @Override
  void operation() {
    implementor.operation();
  }
}

实现部分接口

public interface Implementor {

  void operation();
}

具体实现部分对象

public class ConcreteImplementorA implements Implementor {

  @Override
  public void operation() {
    System.out.println("ConcreteImplementorA operation()");
  }
}

另一个具体实现对象

public class ConcreteImplementorB implements Implementor {

  @Override
  public void operation() {
    System.out.println("ConcreteImplementorB operation()");
  }
}

客户端

public class Client {

  public static void main(String[] args) {
    Abstraction abstraction = new RefinedAbstraction(new ConcreteImplementorA());
    abstraction.operation();
  }

}

消息系统

以一个发送各种消息的业务为例,消息按类型可以分为短信消息,邮件消息,按紧急程度可以分为普通消息,加急消息,整个消息系统可以划分为两个维度。

消息接口

public interface Msg {

  /**
   * 发送消息
   *
   * @param toUser 消息的接受者
   * @param content 要发送消息的内容
   */
  void send(String toUser, String content);
}

实现部分的接口

短信消息

public class SmsMsg implements Msg {

  public void send(String toUser, String content) {
    System.out.println("使用短信消息发送'" + content + "'给" + toUser);
  }
}

邮件消息

public class EmailMsg implements Msg {

  public void send(String toUser, String content) {
    System.out.println("使用邮件消息发送'" + content + "'给" + toUser);
  }
}

抽象消息类

/**
 * 抽象消息类
 */
public abstract class AbstractMsg {

  /**
   * 持有实现部分的对象
   */
  protected Msg msg;

  public AbstractMsg(Msg msg) {
    this.msg = msg;
  }

  public void sendMsg(String toUser, String content) {
    this.msg.send(toUser, content);
  }
}

抽象部分,内部持有一个实现部分的对象

普通消息

/**
 * 普通消息类
 */
public class NormalMsg extends AbstractMsg {

  public NormalMsg(Msg msg) {
    super(msg);
  }

  @Override
  public void sendMsg(String toUser, String content) {
    //对于普通消息,直接调用父类方法发送消息即可
    super.sendMsg(toUser, content);
  }
}

加急消息

/**
 * 加急消息类
 */
public class UrgencyMsg extends AbstractMsg {

  public UrgencyMsg(Msg msg) {
    super(msg);
  }

  @Override
  public void sendMsg(String toUser, String content) {
    content = "【加急】" + content;
    super.sendMsg(toUser, content);
  }

  //扩展功能,监控某个消息的处理状态
  public Object watch(String msgId) {
    //根据给出的消息编码(msgId)查询消息的处理状态
    return null;
  }
}

客户端

public class Client {

  public static void main(String[] args) {
    //发送普通的对象消息
    Msg msg = new SmsMsg();
    AbstractMsg abstractMsg = new NormalMsg(msg);
    abstractMsg.sendMsg("李总", "加班申请速批");
    //发送加急的邮件消息
    msg = new EmailMsg();
    abstractMsg = new UrgencyMsg(msg);
    abstractMsg.sendMsg("李总", "加班申请速批");
  }

}

输出结果为

使用短信消息发送'加班申请速批'给李总
使用邮件消息发送'【加急】加班申请速批'给李总

在上述示例中,我们使用桥接模式解耦了"消息类型"和"消息紧急程度"这个两个独立变化的维度。
后续如果想扩展消息类型如微信消息、钉钉消息等,新建一个类实现Msg接口即可,如果想要扩展紧急程度,
新建一个类继承AbstractMsg就可以了。

桥接模式在JDK中的实现

JDK中的JDBC结构

应用程序依赖于左边的JDBC的API之上,不依赖具体的数据库驱动,两边都可以独立的进行扩展。

总结

优点

  1. 分离抽象和实现部分,提高了系统的灵活性和可扩展性。
  2. 可以在运行时动态地切换实现。

缺点

  1. 要求正确识别出系统中两个独立变化的维度(抽象和实现),增加了系统的设计难度。

本质

桥接模式的本质是分离抽象和实现。分离之后才能独立的变化,才有更好的可扩展性。

广义上的桥接

Java中一个很重要的编程原则就是"面向接口编程",也可以叫做"面向抽象编程",使用接口的程序结构图如下

如果将桥接模式的抽象部分简化一下,暂时不要 RefinedAbstraction 部分,那么就和上图的结构差不多了。

从某个角度来讲,桥接模式就是"面向抽象编程"设计原则的扩展,通过具体实现的接口将抽象部分和具体的实现部分分离开来,
抽象部分相当于是使用实现部分接口的客户程序,这样一来,几乎可以把所有面向抽象编程的程序,都视作桥接模式的体现,
至少也是简化的桥接模式,就算是广义的桥接吧。而Java编程很强调"面向抽象编程",因此,广义的桥接,在Java中可以说是无处不在。

使用场景

  1. 一个类存在两个或多个独立变化的维度,且多个维度都需要独立的进行扩展。
  2. 希望在抽象和实现之间增加更多的灵活性,动态切换具体的实现。

参考

大战设计模式【16】—— 桥接模式
大战设计模式(第二季)【7】———— 从源码看桥接模式
设计模式的征途—8.桥接(Bridge)模式
设计模式(八)——桥接模式
《JAVA设计模式》之桥接模式(Bridge)
桥接模式(Bridge模式)详解
研磨设计模式-书籍

posted @ 2021-09-15 09:38  strongmore  阅读(79)  评论(0编辑  收藏  举报