Java 开放/封闭原则是否说我们可以';你没有改变我们类的接口吗?
请看这节课:Java 开放/封闭原则是否说我们可以';你没有改变我们类的接口吗?,java,oop,solid-principles,Java,Oop,Solid Principles,请看这节课: public class SomeClass { public void method1(){ // do something } public void method2(){ // do something } } 接下来,假设有10个类继承了这个类。因此,如果我们将Parameterr添加到method1(),例如,我们必须更改10个类。这与开/关原则背道而驰。那么,开放/封闭原则是否说我们不能改变类的公共接口呢?是的-有点#8> P “Closed t
public class SomeClass {
public void method1(){
// do something
}
public void method2(){
// do something
}
}
接下来,假设有10个类继承了这个类。因此,如果我们将Parameterr添加到method1(),例如,我们必须更改10个类。这与开/关原则背道而驰。那么,开放/封闭原则是否说我们不能改变类的公共接口呢?是的-有点#8> P
“Closed to changes”位表示您不应该删除public void method1()
签名,也不应该更改其语义(由所有正确实现的具体类提供)
“opentoextension”位允许您(小心地)修改接口,只要前面的接口元素保持原样(结构上和语义上)。您可以尝试以下方法:
public class SomeClass {
@Deprecated
default public void method1(){
method1(#SENTINAL#);
}
public void method1(#TYPE# arg){
if (arg == #SENTINAL#) {
// do something old
} else {
// do something new
}
}
public void method2(){
// do something
}
}
注意:如果参数没有有用的#SENTINAL#值,例如它是一个int
,并且所有值都有效,则此方法可能不起作用。但是,通常会出现一些情况,如任何负值、最小值或最大值、空对象或空对象等。当没有此类sentinal可用时,您可以创建一个私有公共方法,如:
public class SomeClass {
@Deprecated
default public void method1(){
method1(true);
}
public void method1(#TYPE# arg){
method1(false, arg)
}
private void method1(boolean isOldWay, #TYPE# arg) {
if(isOldWay) {
// snore - still old clients
} else {
// yea! new clients are much greener!
}
}
}
PS-我说“接口”,即使您使用的是类。只需将接口视为类的公共元素,在实现类的同时声明。我通常更喜欢为接口编写代码,但这不是OP的问题,也不会改变我的观点(仅仅是修改的地方——如果使用Java 8接口默认实现,则为esp)。这违反了OCP。
接近修改意味着一旦你实现了类并测试了它,你就不应该再修改它了。
有些不可预测的情况是,业务需求突然发生变化,无论设计得多么好,都必须修改类。
在您的案例中,最干净的方法是通过将这个新参数注入到实现类的构造函数中来添加它,或者更好地,注入这个参数的提供者
public class SomeClass{
IProvider _provider;
public SomeClass(IProvider provider){
_provider = provider
}
public void method1(){
var someInput = _provider.Get();
// do something
}
public void method2(){
var someInput = _provider.Get();
// do something
}
}
你必须换10门以上的课。您必须更改将调用
method1()
的每个类,因为这些0参数调用不再有效。我不会像简单的向后兼容性那样担心OCP。当然,如果你控制了所有的调用代码,那就好了。这真的取决于上下文。@JonSkeet,所以如果我控制所有调用代码,我可以更改公共接口吗?若我无法控制,我必须保存旧版本的方法并添加新版本?在此之后,我可以宣布旧版本已弃用?我不同意“开放扩展”允许您修改接口-您有时可能需要这样做,但这违反了OCP,而不是OCP的一部分。OCP说,如果您确实需要重构和修改,那么您可以以一种对未来扩展开放的方式进行重构和修改。e、 g.通过访客/战略模式之类的方式。还可以看到,这有点令人毛骨悚然,但我认为只要客户机代码不需要更改就可以了(最多重新编译,但甚至没有一个括号平滑到正确的paren::smile::)。诚然,这有点违反了“纯”OCP,但我很务实,认为这种精神是通过对接口进行完全兼容的更改来维持的——这难道不是默认方法实际上进入语言的原因吗?(太糟糕了,我们不能让他们默认为final
…::哈哈::)当然,实用主义始终是关键(这也是为什么它是一个“原则”而不是“规则”-违反它是一种代码味道,但这并不意味着永远不应该这样做)。