桥接模式是否将抽象与实现分离?

Does the Bridge Pattern decouples an abstraction from implementation?

我从不同的文章中学习了桥接模式,并且根据我的理解实现了它。让我困惑的一件事是桥接模式说

BridgePattern 将抽象与其实现分离,因此两者可以独立变化

这句话是什么意思?实现位于单独的 jar 中吗?

vary independently statement 是什么意思?

考虑提供的 journaldev 文章,详细说明答案。

非常感谢任何帮助。

这个语句只是意味着,你可以在 运行 时间内切换抽象指向的实现者,一切都应该有效(就像在策略模式中一样;但在策略模式中,只有策略是抽象的) . 也可以理解为将两个类分开,这样他们就不必只知道彼此的接口了。

BridgePattern 将抽象与其实现分离.

抽象实现可以独立变化,因为具体class不直接实现抽象(界面)

重点说明: 两个正交的class层次结构抽象层次结构 y 和 实现层次结构 ) 使用组合(而不是继承)链接。这种组合有助于两个层次结构独立变化。

实现从不涉及抽象。抽象包含实现接口作为成员(通过组合)。

回到您关于 journaldev 文章中示例代码的问题:

形状是抽象

三角形是重新定义的抽象

颜色为执行者

RedColor 是 ConcreteImplementor

一个具体的 Shape 对象:Triangle 扩展了 Shape 但没有实现 颜色界面。

public class Triangle extends Shape{
}

RedColorGreenColor 实际上实现了 Color 接口。

Concrete Shape 对象(Triangle)独立于实现抽象(即 Color 接口)。

Shape tri = new Triangle(new RedColor());

这里Triangle包含一个具体的Color对象(Composition) .如果 Color 抽象(接口)发生变化,RedColorGreenColor 负责实现Color 接口的抽象。

ShapesTriangle 不受 Color 接口合同变化的影响。所以 Color 界面可以独立变化。这是可能的,因为 Shape 持有使用 Composition 而不是 implementation.

的合约

总而言之,

  1. 桥是一种结构模式
  2. 抽象和实现在编译时不受约束
  3. 抽象和实现 - 两者都可以在不影响客户端的情况下发生变化

在以下情况下使用桥接模式:

  1. 你要运行-时间绑定的执行,
  2. 你有来自耦合接口和大量实现的 classes 的激增,
  3. 您想在多个对象之间共享一个实现,
  4. 您需要映射正交 class 层次结构。

有用的链接:

tutorialspoint文章

dzone篇文章

oodesign

sourcemaking

相关post:

When do you use the Bridge Pattern? How is it different from Adapter pattern?

对我来说,桥牌并不是 GOF 圣经中最重要的 DP,因为它主要是 Strategy 的衍生产品。由于其他一些还没有那么成熟的模式(工厂方法?)它意味着比其他模式更多的具有抽象 classes 持有行为的继承,因此不太普遍适用。

主要是战略在做大事,但战略的一个主要问题是战略通常需要了解其背景。

在某些语言中,这导致策略被声明为上下文的友元,或者在 Java 中定义为内部 classes 的策略。

这意味着上下文通常以了解各种具体策略的存在而告终。您可以通过使用 setStrategy() 函数来避免这种情况,但是由于效率原因(您想直接操作上下文的数据结构),从具体策略到上下文的反向依赖通常会存在。

Bridge 解决了这个问题,因为 Strategy 的上下文现在是抽象的,但仍然是 class 先验的,因为它至少有 Strategy 的代码。它通常应该定义一个访问 API 足以让具体的策略使用,可能有漏洞,即抽象方法。您在 AbstractStragey 上的操作签名中出现了 AbstractContext,这很好。

所以在我看来,Bridge 通过使上下文足够具体以使策略起作用来完成策略,但仍然足够抽象以使其可以正交细化 w.r.t。具体策略(在实现具体策略实际使用的上下文的抽象 API 时具有反馈效果)。

看待桥的一种更简单的方式是说 AbstractStrategy 操作应该始终将抽象作为参数,而不是真正深入了解它们的上下文。

更准确地回答 OP 问题:

what is meaning of this statement? Is implementation resides at in separate jar ?

是的,确实,通常您可以在包中定义抽象和实现器 "base"(它们可以是接口)。每个具体的实现器都可以驻留在一个包 "implXX" 中。具体上下文可以驻留在单独的包中 "contXX"。依赖图中没有循环,每个人都依赖于 base,new "contXX" 和 "implXX" 可以独立定义(它们之间完全没有依赖关系)因此 OP 中的粗体声明。

what is meaning of vary independently statement ?

想想eclipse中的编辑器插件;它必须处理按钮和点击的动作(就像一个策略),但策略需要做的实际动作是对编辑器状态本身起作用(例如 "highlight text")。您以抽象的方式定义编辑器拥有的内容,包括它具有用于点击和按键的处理程序以及突出显示和导航功能的事实,甚至这些都可以被具体的编辑器覆盖(闪光而不是突出显示)。那是一座桥梁,您可以独立定义新的编辑器和新的处理程序。

通过一些依赖项注入(例如 Google guice)或一些手动工厂代码或组件定向从外部干净地设置策略,您可以非常低地耦合应用程序的各个部分。

considering the provided journaldev article, elaborate the answer.

老实说,我认为这不是 DP 的最佳应用,因为 Color 实现似乎不太关心它们的上下文。您应该在此处使用 Decorator,因为 Color 是独立于 Shape 的关注点。

查看这些幻灯片,了解使用装饰器的解决方案(抱歉,部分法语)。 https://www-licence.ufr-info-p6.jussieu.fr/lmd/licence/2015/ue/3I002-2016fev/cours/cours-9.pdf(幻灯片 16-18)基于此处介绍的示例: https://www-licence.ufr-info-p6.jussieu.fr/lmd/licence/2015/ue/3I002-2016fev/cours/cours-4.pdf 幻灯片 10 到 15。

在那个例子中,如果 "updateInertie" 是 Forme 的成员,我们将需要 Bridge,这听起来并不荒谬。 Bridge 再次更多地作为其他模式的组合出现。