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

桥接模式(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)

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 3,734评论 0 14
  • 1 场景问题# 1.1 发送提示消息## 考虑这样一个实际的业务功能:发送提示消息。基本上所有带业务流程处理的系统...
    七寸知架构阅读 4,966评论 5 63
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,905评论 1 15
  • 1.初识桥接模式 将抽象部分与它的实现部分分离,使它们都可以独立地变化。 Abstraction:抽象部分的接口。...
    王侦阅读 903评论 0 7
  • 彼岸焦点分享第21天 昨天看到群里老师的分享,说在陪伴孩子时遇到的困惑,不知该怎样用焦点的方法去引领孩子。...
    彼岸_8b4b阅读 223评论 0 0