假设有一个主题主题。
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原则,您是否仍考虑继承?”
如果RealSubject
和EnhancedSubject
在您的控制之下并以相同的生命周期发布,则再次使用继承是安全的,但是直接依赖于具体的实现会导致脆弱的代码。
希望引导您使用接口(interface)实现的另一点是单位
测试。
例如,在您要应用单元测试的情况下,将RealSubject
的模拟依赖项注入(inject)到Proxy
的Subject
实现中会容易得多,以便您可以专门测试Proxy
类,而不必完全测试整个对象层次结构RealSubject
和EnhancedSubject
,只是为了确认EnhancedSubject
的行为符合预期。
我想可以这样说,如果这都是一个非常简单的API,并且将来不会改变,那么具体实现就更简单了。而且保持简单愚蠢(K.I.S.S.)是最好的政策之一。
“如果没有主题界面,您仍然可以应用代理模式吗?”
您可以将RealSubject
注入(inject)另一个类并在内部使用RealSubject
,但是如果使用RealSubject
的API直接取决于具体的类,则别无选择,只能使用继承。
关于java - 代理模式与覆盖,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3965334/