开放/封闭原则的问题?

Posted

技术标签:

【中文标题】开放/封闭原则的问题?【英文标题】:Issues with the Open/Closed Principle? 【发布时间】:2014-07-07 15:16:36 【问题描述】:

正在阅读 SOLID 设计的开放/封闭原则,并对它的可维护性感到好奇。

假设我有从父类 A 继承的子类 B 和 C。B 具有 B 独有的方法,C 具有 C 独有的方法。父类 A 有两个子类使用的常用方法。

在未来的代码版本中,假设我们有一个新特性,它在 B 类和 C 类之间引入了一个通用方法。我们现在不能将该方法推送到 A 类,因为它违反了“为修改而关闭”部分原则。这似乎引入了代码冗余。不仅如此,从技术上来说,在B类和C类中加入这个新特性,是不是也违反了修改原则?

似乎使用 Open/Closed 方法,您最终会构建不必要的级联子类层次结构,仅仅是因为不允许更改原始代码。这是一个正确的假设/理解吗?

【问题讨论】:

这听起来有点做作,但你可以考虑让 B 和 C 派生自一个共同的基础,而该基础本身是从 A 派生的。很大程度上取决于这个新方法是否应该构成 A 的公共接口的一部分以及该接口是否是抽象的。在将接口公开之前,这种重构是很常见的。 SOLID 可能需要在首字母缩略词中添加另一个字母:P 代表“选择你的战斗”,以强调设计是妥协的事实。阅读更多:martinfowler.com/ieeeSoftware/protectedVariation.pdf 虽然这很老,我认为你应该考虑添加一个新功能不会改变旧功能,所以打开关闭原则就可以了,你不是在修改旧代码,你是添加新的以扩展现有类 【参考方案1】:

你没有水晶球,你看不到未来并预测会发生变更请求。

但是一旦提出变更请求,该领域的另一项变更很可能稍后会发生。

让我们以评论中的汽车为例:在收到所有汽车到现在按喇叭的更改请求的那一刻,您应该考虑是否稍后会再进行此类更改。假设您认为这是一个很好的机会,它只有一件事,那就是重构以使整个情况开放以供扩展而封闭以供修改。因此,现在不仅可以轻松添加鸣喇叭,而且您可以轻松添加下一个此类功能。

您说得对,过早地应用它会使代码膨胀,并且在代码审查期间它还会收到大量YAGNI cmets。

【讨论】:

“在选择需要扩展的代码区域时要小心;在任何地方都应用开闭原则是浪费、不必要的,并且可能导致复杂、难以理解的代码。”弗里曼,埃里克;罗布森,伊丽莎白;贝茨,伯特;凯西塞拉 (2004-10-25)。 Head First 设计模式(Kindle 位置 1588-1589)。奥莱利媒体。 Kindle 版。【参考方案2】:

似乎使用开放式/封闭式方法,您最终会构建一个 子类的不必要的级联层次结构仅仅是因为一个 不允许对原代码进行改动。这是一个 正确的假设/理解?

不,我不认为遵循开放/封闭原则会导致子类的级联层次结构。

首先,它只是一个原则或目标。有时,即使对于 SOLID 爱好者来说,向基类添加方法显然是“正确”的方法。

其次,基类中的许多方法(显然会导致更改)一开始就有点代码味道。你看过“favour composition over inheritance”这个短语吗?

【讨论】:

我认为组合优于继承适用于这种情况......假设:Class Car Drive() Brake() Class Corvette : Car CruiseControl() Class Honda : Car DeployAirbag() 新业务要求所有汽车都能按喇叭。这适用于两辆车。这不是对象或组合,它只是将共享方法行为添加到层次结构中。需要编辑 Car 以考虑 Honk() 以避免代码重复。 @roger 的建议是添加一个中间类以避免修改,这似乎会造成我所指示的级联/代码膨胀效果。

以上是关于开放/封闭原则的问题?的主要内容,如果未能解决你的问题,请参考以下文章

深入浅出设计模式——开放封闭原则

开放封闭原则

day21接口类和抽象类,隔离原则,开放封闭原则,多态

Objective C 类别 vs 开放/封闭原则

这是开放/封闭原则吗?如果不

面向对象原则之一 开放封闭原则(开闭原则)