【问题标题】:Does the Bridge Pattern decouples an abstraction from implementation?桥接模式是否将抽象与实现分离?
【发布时间】:2016-05-06 21:35:16
【问题描述】:

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

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

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

独立变化语句的含义是什么?

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

非常感谢任何帮助。

【问题讨论】:

    标签: java design-patterns abstraction bridge


    【解决方案1】:

    BridgePattern 将抽象与其实现分离

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

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

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

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

    形状是抽象

    三角形是重新定义抽象

    颜色是实现者

    RedColor 是 ConcreteImplementor

    一个具体的 Shape 对象:Triangle 扩展了 Shape 但没有实现 Color 接口。

    public class Triangle extends Shape{
    }
    

    RedColorGreenColor 实际上实现了 Color 接口。

    具体形状对象(Triangle)独立于实现抽象(即Color接口)。

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

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

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

    总之,

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

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

    1. 您想要实现的运行时绑定,
    2. 您拥有来自耦合接口和众多实现的大量类,
    3. 您希望在多个对象之间共享一个实现,
    4. 您需要映射正交类层次结构。

    有用的链接:

    tutorialspointartice

    dzone文章

    oodesign文章

    sourcemaking文章

    相关帖子:

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

    【讨论】:

    • 解释得很好,但是在考虑这个例子之后还有一个困惑让我们假设没有桥接模式,你只是为了实现目标而进行继承,例如 RedColor 类扩展三角形并提供它的实现而不是什么需求有变化会有什么影响???
    • 您的意思是三角形扩展了 RedColor 还是 RedColor 扩展了三角形?
    • 使用当前代码,Triangle 可以有 100 多种具体颜色,实现颜色抽象。
    • 应该是反的。 Triangle 扩展了 Color,您可以在构造函数中传递 RedColor 或 GreenColor。如果您在 Color 界面中添加一种方法,您现在必须更改 Triangle(在没有 Bridge 模式的情况下)。使用由颜色和三角形组成的桥式图案就没有这些令人头疼的问题。现在 Concrete Colors 必须在颜色合约中实现更改。
    • 在上面的例子中,你可以独立改变形状和颜色。
    【解决方案2】:

    这句话只是意味着,您可以在运行时切换抽象指向的实现者,一切都应该工作(就像在策略模式中一样;但在策略模式中,只有策略是抽象的)。 也可以理解为将两个类分开,这样它们之间就不必只了解它们的接口了。

    【讨论】:

      【解决方案3】:

      对我来说,Bridge 并不是 GOF 圣经中最重要的 DP,因为它主要是 Strategy 的衍生品。作为其他一些没有那么好老化的模式(工厂方法?),它意味着与其他模式相比,抽象类拥有更多的继承行为,因此不太普遍适用。

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

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

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

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

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

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

      更准确地回答 OP 问题:

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

      是的,确实,通常您可以在包“base”中定义 Abstraction 和 Implementor(它们可以是接口)。具体实施者可以各自驻留在包“implXX”中。具体上下文可以驻留在单独的包“contXX”中。依赖图中没有循环,每个人都依赖于基础,可以独立定义新的“contXX”和“implXX”(它们之间根本没有依赖关系),因此 OP 中的粗体声明。

      独立变化语句的含义是什么?

      想想eclipse中的一个编辑器插件;它必须处理按钮和点击上的操作(如策略),但策略需要执行的实际操作是对编辑器状态本身进行操作(例如“突出显示文本”)。您以抽象的方式定义编辑器所拥有的内容,包括它具有用于 clics 和按键的处理程序以及突出显示和导航功能的事实,即使这些都可以被具体的编辑器覆盖(flash 而不是突出显示)。这是一座桥梁,您可以独立定义新的编辑器和新的处理程序。

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

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

      老实说,我认为这不是 DP 的最佳应用,因为 Color 实现似乎不太关心它们的上下文。您应该在这里使用装饰器,因为颜色是形状的独立关注点。

      查看这些幻灯片,了解使用装饰器的解决方案(部分是法语,抱歉)。 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 再次更多地作为其他模式的组合出现。

      【讨论】:

        猜你喜欢
        • 2017-11-15
        • 2014-11-08
        • 1970-01-01
        • 1970-01-01
        • 2018-08-12
        • 2013-07-14
        • 1970-01-01
        • 2020-10-28
        • 1970-01-01
        相关资源
        最近更新 更多