假设有一个主题主题。

interface Subject { void request(); }

我们有一个RealSubject类。假设我们要增强RealSubject,我们可以使用环绕RealSubject的代理模式:
class Proxy implements Subject {
   private RealSubject ref;
   void request(){ ... }
}

或者我们可以扩展RealSubject并覆盖该方法
class EnhancedSubject extends RealSubject {
   @Override
   void request() { ... }
}

哪种方法更好?我知道利斯科夫原则;让我们假设EnhancedSubject满足Liskov原理。您还在考虑继承吗?

如果没有接口(interface)Subject(即RealSubject没有实现任何接口(interface)),则似乎“继承和覆盖”是唯一的选择,因为没有接口(interface)要在Proxy模式中实现。如果没有“主题”界面,您是否仍可以应用代理模式?

最佳答案

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

我个人更喜欢使用接口(interface)和代理(或装饰器)模式来实现类似的功能。 (请参阅:第16项:偏爱Effective Java (2nd Edition)的继承而不是继承)

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

在回答第二个问题时,“如果EnhancedSubject满足Liskov原则,您是否仍考虑继承?”

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

希望引导您使用接口(interface)实现的另一点是单位
测试。

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

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

“如果没有主题界面,您仍然可以应用代理模式吗?”
您可以将RealSubject注入(inject)另一个类并在内部使用RealSubject,但是如果使用RealSubject的API直接取决于具体的类,则别无选择,只能使用继承。

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

10-10 18:35