从零开始学设计模式(七)—桥接模式

简介:

桥接模式(Bridage Pattern)

此模式难度等级为中级,属结构型模式,提出者为Gang Of Four

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。

它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

意图

将抽象部分与实现部分分离,使它们都可以独立的变化

主要解决:在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。

何时使用:实现系统可能有多个角度分类,每一种角度都可能变化。

如何解决:把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。

关键代码:抽象类依赖实现类。

解释

现实世界中的例子

考虑到你有一件武器具有不同的魔法,假如允许你让不同的武器与不同的魔法混合。你会怎么做?一为每个不同的魔法功能创建多个武器副本,二你会根据需要为武器创建单独的魔法并设置它。桥接模式就是你的第二选择

简而言之

桥接模式是关于更喜欢组合而不是继承。实现细节从一个层次结构派生到另一个具有单独层次结构的对象

维基百科

桥接模式是软件工程中使用的一种设计模式,旨在“将抽象与其实现分离,以便两者可以独立变化”

程序示例

以上面翻译中我们现实世界中的武器例子。如下来建造武器Weapon和魔法Enchantment的组合结构。

image.png
首先编写武器组织结构代码:

public interface Weapon {
  void wield();
  void swing();
  void unwield();
  Enchantment getEnchantment();
}

public class Sword implements Weapon {

  private final Enchantment enchantment;

  public Sword(Enchantment enchantment) {
    this.enchantment = enchantment;
  }

  @Override
  public void wield() {
    LOGGER.info("The sword is wielded.");
    enchantment.onActivate();
  }

  @Override
  public void swing() {
    LOGGER.info("The sword is swinged.");
    enchantment.apply();
  }

  @Override
  public void unwield() {
    LOGGER.info("The sword is unwielded.");
    enchantment.onDeactivate();
  }

  @Override
  public Enchantment getEnchantment() {
    return enchantment;
  }
}

public class Hammer implements Weapon {

  private final Enchantment enchantment;

  public Hammer(Enchantment enchantment) {
    this.enchantment = enchantment;
  }

  @Override
  public void wield() {
    LOGGER.info("The hammer is wielded.");
    enchantment.onActivate();
  }

  @Override
  public void swing() {
    LOGGER.info("The hammer is swinged.");
    enchantment.apply();
  }

  @Override
  public void unwield() {
    LOGGER.info("The hammer is unwielded.");
    enchantment.onDeactivate();
  }

  @Override
  public Enchantment getEnchantment() {
    return enchantment;
  }
}

其次编写分离的魔法组织结构代码:

public interface Enchantment {
  void onActivate();
  void apply();
  void onDeactivate();
}

public class FlyingEnchantment implements Enchantment {

  @Override
  public void onActivate() {
    LOGGER.info("The item begins to glow faintly.");
  }

  @Override
  public void apply() {
    LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand.");
  }

  @Override
  public void onDeactivate() {
    LOGGER.info("The item's glow fades.");
  }
}

public class SoulEatingEnchantment implements Enchantment {

  @Override
  public void onActivate() {
    LOGGER.info("The item spreads bloodlust.");
  }

  @Override
  public void apply() {
    LOGGER.info("The item eats the soul of enemies.");
  }

  @Override
  public void onDeactivate() {
    LOGGER.info("Bloodlust slowly disappears.");
  }
}

最后上面两个组织层次都起作用,自动桥接:

Sword enchantedSword = new Sword(new SoulEatingEnchantment());
enchantedSword.wield();
enchantedSword.swing();
enchantedSword.unwield();
// The sword is wielded.
// The item spreads bloodlust.
// The sword is swinged.
// The item eats the soul of enemies.
// The sword is unwielded.
// Bloodlust slowly disappears.

Hammer hammer = new Hammer(new FlyingEnchantment());
hammer.wield();
hammer.swing();
hammer.unwield();
// The hammer is wielded.
// The item begins to glow faintly.
// The hammer is swinged.
// The item flies and strikes the enemies finally returning to owner's hand.
// The hammer is unwielded.
// The item's glow fades.

应用场景

当遇到如下情况时你应该使用桥接模式:

  • 你希望避免抽象与其实现之间的永久绑定。例如,在运行时必须选择或切换实现时,可能会出现这种情况
  • 抽象和它们的实现都应该通过子类化来扩展。在这种情况下,Bridge模式允许你组合不同的抽象和实现,并独立地扩展它们
  • 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
  • 抽象中的具体实现发生变化时不应影响客户端;也就是说,客户端他们的代码不应该被重新编译
  • 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用
  • 你想在多个对象之间共享一个实现(也许使用引用计数),这个事实应该对客户端隐藏。一个简单的例子是Coplien的String类,其中多个对象可以共享相同的String表示

写在最后

对于一个类存在两个独立变化的维度,使用桥接模式是再适合不过了。

将抽象和实现放在两个不同的类层次中,使它们可以独立地变化。——《Head First 设计模式》

将类的功能层次结构和实现层次结构相分离,使二者能够独立地变化,并在两者之间搭建桥梁,实现桥接。—— 《图解设计模式》

类的功能层次结构:父类具有基本功能,在子类中增加新的功能;

类的实现层次结构:父类通过声明抽象方法来定义接口,子类通过实现具体方法来实现接口;

桥接模式中有四个角色:

抽象化角色:使用实现者角色提供的接口来定义基本功能接口。

持有实现者角色,并在功能接口中委托给它,起到搭建桥梁的作用;

注意,抽象化角色并不是指它就是一个抽象类,而是指抽象了实现。

改善后的抽象化角色:作为抽象化角色的子类,增加新的功能,也就是增加新的接口(方法);与其构成类的功能层次结构;

实现者角色:提供了用于抽象化角色的接口;它是一个抽象类或者接口。

具体的实现者角色:作为实现者角色的子类,通过实现具体方法来实现接口;与其构成类的实现层次结构。

最后,如果抽象和实现两者做不到独立地变化,就不算桥接模式。

下一篇文章我们将学习结构性模式中的过滤器模式(Filter Pattern)

码字不易,各位看官如果喜欢的话,请给点个喜欢 ️,关注下我,我将努力持续不断的为大家更新

目录
相关文章
|
6月前
|
设计模式 开发者
【设计模式】第七篇:和我一起简单认识桥接模式
实现的意思并不是指抽象的派生类,而是指通过组合来代替继承关系,从而降低抽象和具体实现产品两个可变换维度之间的耦合,就像我们的相机品牌和相机产品类型之间的分离
54 4
|
7月前
|
设计模式 Java
【设计模式】JAVA Design Patterns——Bridge(桥接模式)
【设计模式】JAVA Design Patterns——Bridge(桥接模式)
【设计模式】JAVA Design Patterns——Bridge(桥接模式)
|
7月前
|
设计模式 Oracle Java
设计模式--- 桥接模式、JDBC 源码剖析(桥接)
设计模式--- 桥接模式、JDBC 源码剖析(桥接)
123 2
|
7月前
|
设计模式
设计模式之桥接模式
设计模式之桥接模式
|
7月前
|
设计模式 Linux Windows
【设计模式】桥接模式
【设计模式】桥接模式
|
2月前
|
设计模式 PHP 开发者
PHP中的设计模式:桥接模式的解析与应用
在软件开发的浩瀚海洋中,设计模式如同灯塔一般,为开发者们指引方向。本文将深入探讨PHP中的一种重要设计模式——桥接模式。桥接模式巧妙地将抽象与实现分离,通过封装一个抽象的接口,使得实现和抽象可以独立变化。本文将阐述桥接模式的定义、结构、优缺点及其应用场景,并通过具体的PHP示例代码展示如何在实际项目中灵活运用这一设计模式。让我们一起走进桥接模式的世界,感受它的魅力所在。
|
3月前
|
设计模式 自然语言处理 算法
PHP中的设计模式:桥接模式的深入探索与应用
在PHP开发中,理解并运用设计模式是提升代码质量与可维护性的关键。本文聚焦于桥接模式——一种结构型设计模式,它通过封装一个抽象的接口,将实现与抽象分离,从而使得它们可以独立变化。不同于传统摘要的概述式表述,本文将以故事化的情境引入,逐步解析桥接模式的精髓,通过PHP代码示例详细展示其在实际项目中的应用,旨在为读者提供一个既深刻又易于理解的学习体验。
27 1
|
3月前
|
设计模式 Java
Java设计模式-桥接模式(9)
Java设计模式-桥接模式(9)
|
2月前
|
设计模式 Java
Java设计模式之桥接模式
这篇文章介绍了Java设计模式中的桥接模式,包括桥接模式的目的、实现方式,并通过具体代码示例展示了如何分离抽象与实现,使得两者可以独立变化。
44 0
|
4月前
|
设计模式 XML 存储
【七】设计模式~~~结构型模式~~~桥接模式(Java)
文章详细介绍了桥接模式(Bridge Pattern),这是一种对象结构型模式,用于将抽象部分与实现部分分离,使它们可以独立地变化。通过实际的软件开发案例,如跨平台视频播放器的设计,文章阐述了桥接模式的动机、定义、结构、优点、缺点以及适用场景,并提供了完整的代码实现和测试结果。桥接模式适用于存在两个独立变化维度的系统,可以提高系统的可扩展性和灵活性。
【七】设计模式~~~结构型模式~~~桥接模式(Java)