圣诞大减价开始了!

意图

是一种结构设计模式,它允许您将一个大型类或一组密切相关的类分割为两个单独的层次结构——抽象和实现——这两个层次结构可以彼此独立地进行开发。

桥梁设计模式

问题

抽象?实现吗?听起来可怕吗?保持冷静,让我们考虑一个简单的例子。

假设你有一个几何图形形状带有一对子类的类:而且广场.您希望扩展这个类层次结构以合并颜色,因此您计划创建红色的而且蓝色的形状子类。但是,由于已经有了两个子类,因此需要创建四个类组合,例如BlueCircle而且RedSquare

桥型问题

类组合的数量以几何级数增长。

向层次结构中添加新的形状类型和颜色将使其呈指数级增长。例如,要添加一个三角形形状,您需要引入两个子类,每个子类对应一个颜色。在此之后,添加新颜色需要创建三个子类,每个类对应一个形状类型。我们走得越远,情况就越糟。

解决方案

出现这个问题是因为我们试图在两个独立的维度上扩展形状类:通过形式和颜色。这是类继承中非常常见的问题。

桥接模式试图通过从继承切换到对象组合来解决这个问题。这意味着您将其中一个维度提取到一个单独的类层次结构中,这样原始类将引用新层次结构的对象,而不是将其所有状态和行为都放在一个类中。

桥式模式提出的解决方案

可以通过将类层次结构转换为几个相关的层次结构来防止类层次结构的膨胀。

按照这种方法,我们可以将与颜色相关的代码提取到它自己的类中,它有两个子类:红色的而且蓝色的.的形状类然后获取指向其中一个颜色对象的引用字段。现在,形状可以将任何与颜色相关的工作委托给链接的颜色对象。这一参考资料将成为双方之间的桥梁形状而且颜色类。从现在开始,添加新的颜色将不需要改变形状层次结构,反之亦然。

抽象和实现

GoF的书介绍术语抽象而且实现作为桥定义的一部分。在我看来,这些术语听起来太学术了,使模式看起来比实际情况更复杂。在阅读了带有形状和颜色的简单示例之后,让我们来破译GoF书中可怕的文字背后的含义。

抽象(也称为接口)是一些实体的高级控制层。这个层不应该单独做任何实际工作。它应该把工作委托给实现层(也称为平台).

注意,我们不是在谈论接口抽象类从你的编程语言。这不是一回事。

在讨论实际应用程序时,抽象可以由图形用户界面(GUI)表示,实现可以是底层操作系统代码(API), GUI层在响应用户交互时调用API。

一般来说,你可以在两个独立的方向上扩展这样一个应用:

  • 拥有几个不同的gui(例如,为常规客户或管理员量身定制)。
  • 支持几种不同的api(例如,能够在Windows、Linux和macOS下启动应用程序)。

在最坏的情况下,这个应用程序可能看起来像一个巨大的意大利面碗,在代码中有数百个条件连接不同类型的GUI和各种api。

在模块化代码中管理更改要容易得多

即使对单片代码库进行简单的更改也是相当困难的,因为您必须理解整个事情很好。对较小的、定义良好的模块进行更改要容易得多。

您可以通过将与特定接口平台组合相关的代码提取到单独的类中来为这种混乱带来秩序。然而,很快你就会发现确有其事很多这些类的。类层次结构将呈指数级增长,因为添加新的GUI或支持不同的API将需要创建越来越多的类。

让我们尝试使用Bridge模式来解决这个问题。它建议我们将类划分为两个层次结构:

  • 抽象:应用程序的GUI层。
  • 实现:操作系统的api。
跨平台的架构

这是构造跨平台应用程序的一种方法。

抽象对象控制应用程序的外观,将实际工作委托给链接的实现对象。不同的实现是可互换的,只要它们遵循一个共同的界面,从而使相同的GUI可以在Windows和Linux下工作。

因此,您可以在不涉及与api相关的类的情况下更改GUI类。而且,添加对另一个操作系统的支持只需要在实现层次结构中创建一个子类。

结构

桥梁设计模式 桥梁设计模式
  1. 抽象提供高级控制逻辑。它依赖于实现对象来完成实际的底层工作。

  2. 实现声明所有具体实现的通用接口。抽象只能通过这里声明的方法与实现对象通信。

    抽象可以列出与实现相同的方法,但通常抽象声明一些复杂的行为,这些行为依赖于实现声明的各种基本操作。

  3. 具体实现包含平台特定的代码。

  4. 提炼抽象提供控制逻辑的变体。像它们的父类一样,它们通过通用实现接口使用不同的实现。

  5. 通常,客户端只对抽象感兴趣。然而,将抽象对象与一个实现对象联系起来是客户端的工作。

伪代码

这个例子说明了如何模式可以帮助划分管理设备及其远程控制的应用程序的整体代码。的设备类充当实现,而远程S作为抽象。

桥模式示例的结构

原始的类层次结构分为两部分:设备和远程控制。

基远程控制类声明了一个引用字段,将其与设备对象链接起来。所有遥控器都通过通用设备接口与设备一起工作,这让同一个遥控器支持多种设备类型。

您可以独立于设备类开发远程控制类。所需要的就是创建一个新的远程子类。例如,一个基本的遥控器可能只有两个按钮,但你可以用额外的功能来扩展它,比如额外的电池或触摸屏。

客户端代码通过远程的构造函数将所需的远程控制类型与特定的设备对象链接起来。

//“抽象”定义了两个类层次结构的“控制”部分的接口。它维护对“实现”层次结构对象的引用,并将所有实际工作委托给该对象。remoteccontrol类是受保护的字段设备:Device)是this.device =设备方法togglePower()是if (Device . isenabled())那么Device .disable() else Device .enable()方法volumeDown()是Device . setvolume (Device . getvolume() - 10)方法volumeUp()是Device . setvolume (Device . getvolume() + 10)方法channelDown()是Device . setchannel (Device . getchannel() - 1)方法channelUp()是Device . setchannel (Device . getchannel() + 1) //你可以从抽象层次结构中扩展类//独立于设备类。//“实现”接口声明了所有具体实现类的通用方法。它不必匹配//抽象的接口。事实上,这两个接口可以完全不同。通常,实现接口//只提供原语操作,而抽象接口//基于这些原语定义了更高级别的操作。interface Device is method isEnabled() method enable() method disable() method getVolume() method setVolume(percent) method getChannel() method setChannel(channel) //所有设备都使用同一个接口。类Tv实现Device is //… class Radio implements Device is // ... // Somewhere in client code. tv = new Tv() remote = new RemoteControl(tv) remote.togglePower() radio = new Radio() remote = new AdvancedRemoteControl(radio)

适用性

当您希望划分和组织具有某些功能的多个变体的单一类(例如,如果类可以与各种数据库服务器一起工作)时,请使用Bridge模式。

班级规模越大,就越难搞清楚它是如何运作的,做出改变所需的时间也就越长。对功能的一个变体所做的更改可能需要在整个类中进行更改,这通常会导致错误或没有解决一些关键的副作用。

桥接模式允许您将单块类分割为几个类层次结构。在此之后,您可以独立于其他层次结构中的类更改每个层次结构中的类。这种方法简化了代码维护,并将破坏现有代码的风险降至最低。

当您需要在几个正交的(独立的)维度上扩展一个类时,请使用该模式。

Bridge建议为每个维度提取单独的类层次结构。原始类将相关工作委托给属于这些层次结构的对象,而不是自己完成所有工作。

如果需要在运行时切换实现,请使用桥接。

尽管Bridge模式是可选的,但它允许您在抽象中替换实现对象。这就像给字段赋一个新值一样简单。

顺便说一下,这最后一项是为什么这么多人混淆桥和策略模式。记住,模式不仅仅是构造类的一种特定方式。它还可以传达意图和正在解决的问题。

如何实施

  1. 确定类中的正交维。这些独立的概念可以是:抽象/平台、域/基础设施、前端/后端或接口/实现。

  2. 查看客户端需要哪些操作,并在基本抽象类中定义它们。

  3. 确定所有平台上可用的操作。在通用实现接口中声明抽象需要的对象。

  4. 对于域内的所有平台,创建具体的实现类,但要确保它们都遵循实现接口。

  5. 在抽象类内部,为实现类型添加一个引用字段。抽象将大部分工作委托给该字段中引用的实现对象。

  6. 如果您有几个高级逻辑的变体,那么通过扩展基本抽象类为每个变体创建细化的抽象。

  7. 客户端代码应该将一个实现对象传递给抽象的构造函数,以便将其中一个与另一个关联起来。在此之后,客户端可以忘记实现,只使用抽象对象。

利与弊

  • 你可以创建独立于平台的类和应用。
  • 客户端代码使用高级抽象。它不会暴露于平台细节。
  • 打开/关闭原则.您可以相互独立地引入新的抽象和实现。
  • 单一责任原则.您可以在抽象中关注高级逻辑,在实现中关注平台细节。
  • 通过将模式应用于高内聚类,可以使代码更加复杂。

与其他模式的关系

  • 通常是预先设计的,允许您独立地开发应用程序的各个部分。另一方面,适配器通常与现有应用程序一起使用,以使一些不兼容的类很好地协同工作。

  • 状态策略(在某种程度上适配器)的结构非常相似。实际上,所有这些模式都基于组合,即将工作委托给其他对象。然而,它们都解决不同的问题。模式不仅仅是以特定的方式构造代码的秘方。它还可以将模式解决的问题传达给其他开发人员。

  • 你可以使用抽象工厂随着.定义的一些抽象时,这种配对非常有用只能使用特定的实现。在这种情况下,抽象工厂可以封装这些关系并对客户端代码隐藏复杂性。

  • 你可以结合构建器: director类扮演抽象的角色,而不同的构建器充当实现。

代码示例

c#中的桥c++中的桥围棋中的桥爪哇桥PHP中的桥Python桥红宝石桥铁锈桥雨燕桥TypeScript中的桥

Baidu
map