设计模式之桥接模式(Bridge Design Pattern)

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

桥梁模式从名字来看很具象,但从定义来看又很抽象难懂。对于初学设计模式,桥梁最难理解的一种模式之一。

本文我们从一个飞机的例子慢慢演化,来理解桥梁模式。

  • 按用途(维度一)区分,飞机可分为客运飞机、货运飞机、私人飞机。
//飞机
interface Aircraft {

  public void purpose();
}

//客运飞机
class PassengerAircraft {

  public void purpose(){
    //运客
  }

}

//货运飞机
class CargoAircraft {

  public void purpose(){
    //运货
  }

}

//私人飞机
class PrivateAircraft {

  public void purpose(){
    //运私人
  }

}

  • 按动力(维度二)区分,飞机可分为螺旋桨飞机、喷气式飞机。

(为了图可以简单一些,省略了私人飞机的类图)

我们看到当抽象Aircraft扩展时(添加了动力power),实现类也要跟着扩展了(子类从原来三个变成了六个)。

可想如果再增加飞行速度(维度三)、其他(维度...),子类就会成指数增加了。而且只要扩展抽象,子类也要跟着扩展;修改抽象,也会影响到所有子类。

所以需要让抽象与实现进行解耦,让抽象和实现可以独立变化。如何做呢?如果你看过《多用组合少且继承的设计思想》会知道,桥接模式就是这种思想最直接的表现形式。

现在我们运用组合的方式来从头开始重构一下。

  • 按用途(维度一)区分,飞机可分为客运飞机、货运飞机、私人飞机。
interface Purposeable {
    public void purpose();
}

//货运
class Cargo implements Purposeable {

  public void purpose(){
    System.out.println("运货");
  }
}

//客运
class Passenger implements Purposeable {

  public void purpose(){
    System.out.println("运客");
  }

}


//飞机
abstract class Aircraft {
  Purposeable purposeImpl; 

  public Aircraft(Purposeable purposeImpl) {
    this.purposeImpl = purposeImpl;
  }
  
  public void purpose(){
    this.purposeImpl.purpose();
  }
}

//客运飞机
class PassengerAircraft {

  public PassengerAircraft(){
    super(new Passenger());
  }


}

//货运飞机
class CargoAircraft {

  public CargoAircraft(){
    super(new Cargo());
  }

}


public  class Demo implements {
    public static void main(String[] args) {
      Aircraft passengerAircraft= new PassengerAircraft();
      passengerAircraft.purpose();
      Aircraft cargoAircraft= new CargoAircraft();
      cargoAircraft.purpose();
    }
}

//执行结果
运客
运货

重构之后,抽象接口Aircaft做成了抽象类,purpose的实现, 并不在抽象Aircaft中,而且与另一个抽象Purposeable进行组合,purpose的实现交由Purposeable的子类来实现。通过这种方式purpose可以做独立变化,跟Aircaft没有关系。现在抽象已经与实现进行的解耦,并且实现也可以独立变化,但是抽象如何独立变化呢?我们继续往下看。

  • 按动力(维度二)区分,飞机可分为螺旋桨飞机、喷气式飞机。
interface Powerable {
    public void power();
}

//喷气式
class Jet implements Powerable{

  public void power(){
    System.out.println("喷气");
  }
}

//螺旋桨
class Propeller implements Powerable{

  public void power(){
    System.out.println("螺旋桨");
  }

}

interface Purposeable {
    public void purpose();
}

//货运
class Cargo implements Purposeable {

  public void purpose(){
    System.out.println("运货");
  }
}

//客运
class Passenger implements Purposeable {

  public void purpose(){
    System.out.println("运客");
  }

}


//飞机
abstract class Aircraft {
  Purposeable purposeImpl; 
  Powerable powerImpl;

  protected Aircraft(Purposeable purposeImpl){
    this.purposeImpl= purposeImpl;
  }

  protected Aircraft(Purposeable purposeImpl, Powerable powerImpl){
    this.purposeImpl= purposeImpl;
    this.powerImpl = powerImpl;
  }
  
  public void purpose(){
    this.purposeImpl.purpose();
  }

  public void power(){
    this.powerImpl .power();
  }
}

//客运飞机
class PassengerAircraft {

  public PassengerAircraft(){
    super(new Passenger());
  }

  public PassengerAircraft(Powerable powerImpl){
    super(new Passenger(),powerImpl);
  }

}

//货运飞机
class CargoAircraft {

  public CargoAircraft(){
    super(new Cargo());
  }

  public CargoAircraft(Powerable powerImpl){
    super(new Cargo(),powerImpl);
  }

}


public  class Demo implements {
    public static void main(String[] args) {
      //螺旋桨客运飞机
      Aircraft propellerPassengerAircraft= new PassengerAircraft(new Propeller());
      propellerPassengerAircraft.purpose();
      propellerPassengerAircraft.power();
      //喷气客运飞机
      Aircraft jetPassengerAircraft= new PassengerAircraft(new Jet());
      jetPassengerAircraft.purpose();
      jetPassengerAircraft.power();
      //螺旋桨货运飞机
      Aircraft propellerCargoAircraft= new CargoAircraft(new Propeller());
      propellerCargoAircraft.purpose();
      propellerCargoAircraft.power();
      //喷气货运飞机
      Aircraft jetCargoAircraft= new PassengerAircraft(new Jet());
      jetCargoAircraft.purpose();
      jetCargoAircraft.power();
    }
}

//执行结果
运客
螺旋桨

运客
喷气

运货
螺旋桨

运货
喷气

我们看到虽然新加了Powerable维度,但是抽象Aircraft并没有新增新的子类,也就是Aircraft扩展了,子可以跟着扩展,只需要做很小的修改。而且因为并没有改变原有的属性和方法,所以对原先的调用者也不会有影响,满足开闭原则。现在抽象也可以独立变化了。

到现在桥梁模式已经学完了,你是否明白了怎么使用。

现在问题来了,为什么要叫桥梁模式呢?难道是类模型看起来像座桥吗?如果你知道,请你评论告诉我。

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值