java - 代理模式与覆盖

标签 java design-patterns dynamic-proxy

假设有一个接口(interface)Subject。

interface Subject { void request(); }

我们有一个 RealSubject 类。假设我们想要增强 RealSubject,我们可以使用环绕 RealSubject 的代理模式:

class Proxy implements Subject { 
   private RealSubject ref;
   void request(){ ... }
}

或者我们可以扩展 RealSubject 并覆盖该方法

class EnhancedSubject extends RealSubject {
   @Override
   void request() { ... }
}

哪种方法更好?我知道 Liskov 原则;让我们假设 EnhancedSubject 满足 Liskov 原则。你还考虑继承吗?

如果没有接口(interface) Subject(即 RealSubject 不实现任何接口(interface)),似乎“继承和覆盖”是唯一的选择,因为在代理模式中没有接口(interface)可以实现。如果没有 Subject 接口(interface),你还能应用 Proxy 模式吗?

最佳答案

在回答您的第一个问题“哪种方法更好”时?

我个人更喜欢使用接口(interface)和代理(或装饰器)模式来实现类似的东西。 (参见:第 16 条:优先考虑 Effective Java (2nd Edition) 的继承)

如果父类(super class) (RealSubject) 不受您的控制,即在同一个包中,并且是专门为扩展设计和记录的,那么从一个版本到另一个版本对其实现的任何更改都可能会破坏您的实现子类 (EnhancedSubject)。基本上我要说的是:直接依赖于具体的实现会导致代码脆弱。

针对你的第二个问题,“如果EnhancedSubject满足Liskov原则,你还考虑继承吗?

如果 RealSubjectEnhancedSubject 在您的控制之下并以相同的生命周期发布,但是直接依赖于具体实现会导致代码脆弱。

另一个有希望影响您使用接口(interface)实现的点是 Unit 测试。

例如,使用您想要应用单元测试的情况,将 RealSubject 的模拟依赖项注入(inject)到您的 Proxy 实现中会容易得多Subject 这样您就可以专门测试 Proxy 类,而不必完全测试整个对象层次结构,RealSubjectEnhancedSubject,只是为了确认 EnhancedSubject 的行为符合预期。

我想可以这么说,如果它都是一个非常简单的 API,并且它在未来几乎不会改变,那么具体的实现只会更简单。保持简单愚蠢 (K.I.S.S.) 是最好的政策之一。

如果没有 Subject 接口(interface),你还能应用 Proxy 模式吗?” 您可以将 RealSubject 注入(inject)另一个类并在内部使用 RealSubject,但是如果使用 RealSubject 的 API 直接依赖于具体类,则您没有其他选择选择,而是使用继承。

关于java - 代理模式与覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3965334/

相关文章:

java - 如何使用枚举值获取枚举

java - jain sip processResponse() 没有被调用

haskell - 在 Haskell 上,表示纸牌游戏的纸牌效果的语言方式是什么?

algorithm - 如何克服多个数据库上的数据不匹配

c# - FluentAssertions Should().BeEquivalentTo 不比较 EF 动态代理上的运行时派生类型

java - 代理和动态代理模式之间的区别

java - 不同主题的 Spring mvc ResourceBundleMessageSource

java - 带有 Jscrollpane 的 jfx 中的样式问题

java - 如何根据 POJO 中的另一个值更改变量的值?

c# - 复用接口(interface)方法调用到单个委托(delegate)中并解复用