重学设计模式(三、设计模式-桥接模式)

发布于 2022-06-03 00:09

1、桥接模式

有一句诗,叫“横看成岭侧成峰,远近高低各不同”,在现实生活中,我们常常会遇到某些东西可以从两个或多个维度去分类。比如:电脑可以按类型分类(笔记本、台式、平板)、也可以按品牌分类(戴尔、华硕、苹果),如果用继承方式,就会呈现如下效果:

电脑

这样做呢违反了我们的单一职责原则,一个类承担了两个职责,比如戴尔台式机,一个是品牌一个是电脑类型。

我们要新增一个品牌呢?就要新增好几个类,这样不仅子类多,且扩展困难。我们的桥接模式就是用来解决这个问题的。其实这就是合成复用原则的体现。

1.1、什么是桥接模式

  • 定义

桥接模式是一种结构型设计模式,它允许您将一个大类或一组密切相关的类拆分为两个独立的层次结构——抽象和实现——使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

其中一个层次结构(通常称为抽象)将获得对第二层次结构(实现)的对象的引用。

1.2、桥接模式的优缺点

  • 优点

1)抽象与实现分离,扩展能力强;

2)符合开闭原则、符合合成复用原则;

  • 缺点

由于聚合关系建立在抽象层,可能会使代码更加复杂。

1.3、创建方式

以电脑为例:从品牌和类型维度展开

1)电脑品牌接口-IComputerBrand

/**
 * 电脑品牌品牌的共性
 */

public interface IComputerBrand {

 void open()//都能开机
 
 void close()//都能关机
 
 void playGame()//都能玩游戏
 
}

2)品牌的具体实现Dell、Apple

public class Dell implements IComputerBrand{

 @Override
 public void close() {
  System.out.print("戴尔电脑关机");
 }

 @Override
 public void open() {
  System.out.print("戴尔电脑开机");
 }

 @Override
 public void playGame() {
  System.out.print("戴尔电脑玩游戏");
 }

}

public class Apple implements IComputerBrand {
 
 @Override
 public void close() {
  System.out.print("苹果电脑关机");
 }

 @Override
 public void open() {
  System.out.print("苹果电脑开机");
 }

 @Override
 public void playGame() {
  System.out.print("苹果电脑玩游戏");
 }
}

3)电脑类型维度-IComputerType

/**
 * 电脑类型
 */

public abstract class IComputerType {

    private IComputerBrand icb; //聚合
    
    
    public IComputerType(IComputerBrand icb) {
     this.icb = icb;
 }
    
 public void close() {
  icb.close();
 }

 public void open() {
  icb.open();
 }

 public void playGame() {
  icb.playGame();
 }
}

4)电脑类型,台式机和记笔记

public class TaiSComputer extends IComputerType{

 private String name;
 
 public TaiSComputer(IComputerBrand icb) {
  super(icb);
  this.name = "台式机";
 }

 @Override
 public void close() {
  super.close();
  System.out.println("-"+name);
 }

 @Override
 public void open() {
  super.open();
  System.out.println("-"+name);
 }

 @Override
 public void playGame() {
  super.playGame();
  System.out.println("-"+name);
 }
}

public class BjbComputer extends IComputerType{

 private String name;
 
 public BjbComputer(IComputerBrand icb) {
  super(icb);
  this.name = "笔记本";
 }

 @Override
 public void close() {
  super.close();
  System.out.println("-"+name);
 }

 @Override
 public void open() {
  super.open();
  System.out.println("-"+name);
 }

 @Override
 public void playGame() {
  super.playGame();
  System.out.println("-"+name);
 }
}

5)客户端调用

public class Client {

 public static void main(String[] args) {
  
  IComputerType tsj1 = new TaiSComputer(new Dell());
  tsj1.open();
  tsj1.playGame();
  tsj1.close();
  System.out.println("--------");
  IComputerType tsj2 = new BjbComputer(new Apple());
  tsj2.open();
  tsj2.playGame();
  tsj2.close();
  System.out.println("--------");
  IComputerType tsj3 = new TaiSComputer(new Apple());
  tsj3.open();
  tsj3.playGame();
  tsj3.close();
 }
}
  • 案例效果
  • 此时的UML关系图:看起来是不是有点像桥一样一座连接一座。

1.4、总结及建议

桥接模式就是将抽象与其实现分离,以便两者可以独立变化。桥接模式可以取代多重继承的方案,多重继承违背了单一职责原则,复用性较差,类的个数也非常多。桥接模式可以极大的减少子类的个数,从而降低管理和维护成本。

应用场景:

1)当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时,可以使用桥接模式可以解耦这些变化的维度;

2)当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时,可以使用桥接模式。



本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。

相关素材