5

Design Patterns - Elements of Reusable Object-Oriented Software一书中说:

在只有一个实现(一对一)的情况下,不需要创建抽象实现类。这是桥接模式的退化案例;Abstraction 和 Implementor 之间存在一对一的关系。尽管如此,当类的实现更改不得影响其现有客户时,这种分离仍然很有用——也就是说,它们不必重新编译,只需重新链接即可。

我怀疑编译时间的好处,因为我无法想象在 Java 中实现更改会重新编译其超类(在这种情况下是抽象的)的情况。

例如,如果我们有 X 扩展 Y 并且客户这样做:

Y y = new X();  

X 的改变并不意味着 Y 的重新编译(当然,如果我们不想改变 X 的方法签名)

使用桥接模式时完全相同:

YAbstraction yabstraction = new YRefinedAbstraction(new XImplementor());

XImplementor 的变化并不意味着重新编译 YAbstraction。

因此,根据我的说法,这种好处不会出现在 Java 中,并且对于一对一 => 不需要桥接模式。

也许子类的变化会迫使超类用其他语言重新编译?喜欢 SmallTalk 和 C++ 吗?

你有什么意见?

4

2 回答 2

3

在桥接模式中,您有两种类层次结构:一种用于抽象(例如,带有派生类的窗口,如 DialogWindow 和 IconWindow),另一种用于实现器(例如,带有派生类的 WindowImpl,如 XWindowImpl 和 PMWindowImpl)。实现者的接口应该对抽象的客户隐藏。通常,Implementor 提供低级原语,而 Abstraction 根据这些原语构建更高级别的操作,因此在分层良好的系统中,客户端应该不需要查看 Implementor 提供的低级接口。如果有一天,事实证明 WindowImpl 提供的接口不够通用以适应新的 XYZWindowImpl,您保留更改它的自由,因为 WindowImpl 永远不应该由您的客户直接使用,而只能由 Window 及其子类使用。因此,WindowImpl 接口的变化可能需要对 Window 进行修改,但不会传播到客户端。此外,人们经常将实现者隐藏在用于配置网桥的抽象工厂后面。

您描述的桥接模式的优势取决于对抽象的客户隐藏实施者的接口。在 C++ 中,您可以通过简单地不提供头文件来轻松隐藏实施者的接口。在 Java 中,您可以使实施器成为具有包私有成员的抽象类。

在 C++ 中,抽象的客户端不需要重新编译,只需重新链接。在 Java 中,您需要加载类而不是链接,因此您需要做的就是使用新设置和新 jar 文件重新加载应用程序。

例如,想象一下当一个命令行选项或环境变量被一个抽象工厂使用正确类型的具体实施器配置桥接器的情况。在这种情况下,您只需使用新的命令行/环境设置和包含新的 ConcreteImplementor 的新 jar 文件重新加载应用程序。您可以在不重新编译客户端代码的情况下执行此操作。

因此,要直接回答您的问题:在 Java 中,桥模式也确实具有问题中描述的优势。如果您计算从未发生重新链接的事实,则可能在更大程度上。

于 2011-12-04T00:01:22.983 回答
0

Java 没有像 C/C++ 那样的“链接”。但是,我认为这个概念仍然适用:如果实现类位于与抽象不同的库(.jar 文件)中,那么您不必重新打包包含抽象的 .jar 文件。这可以简化复杂系统的维护。

于 2011-12-03T23:54:07.850 回答