问题标签 [open-closed-principle]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
15 回答
9517 浏览

oop - 开放/封闭原则背后的含义和推理是什么?

开放/封闭原则指出软件实体(类、模块等)应该对扩展开放,但对修改关闭。这是什么意思,为什么它是良好的面向对象设计的重要原则?

0 投票
9 回答
926 浏览

language-agnostic - OO 设计,开放/封闭原则问题

我一直在考虑这个面向对象的设计问题,但无法提出令人满意的解决方案,所以我想在这里向人群开放以征求意见。

我有一个代表回合制棋盘游戏的Game类,出于这个问题的目的,我们可以假设它类似于 Monopoly。在我的设计中,我有一个包含方法TakeTurn的Player类。

Game循环遍历所有Player并调用 TakeTurn 方法来完成所有必要的事情以完成转弯。我希望能够拥有 n 个玩家,并且能够将任意数量的玩家设置为电脑玩家。所以,我的想法是有一个 HumanPlayer 类和一个ComputerPlayer类,它们都派生自 Player。

Game只知道Player类,并简单地依次调用每个Player的TakeTurn方法。我的问题在于,ComputerPlayer对象可以完全自动化,即与 Monopoly 示例保持一致,可以使用某种逻辑决定购买房产。现在,对于HumanPlayer对象,它需要从实际用户那里获得输入才能购买房产,例如,这似乎暗示了不同的界面,并且可能意味着它们不应该派生

如果不让Game类明确知道各种Player类的实际实现,我就无法为这个问题提出一个好的解决方案。我总是可以在Game类中假设永远只有人类和计算机玩家并有效地关闭它以进行扩展,但这似乎不是好的 OO 编程。

对此的任何意见将不胜感激。

0 投票
2 回答
1852 浏览

c++ - 访客模式+开放/封闭原则

是否可以实现尊重开放/封闭原则的访问者模式,但仍然能够添加新的可访问类?

开放/封闭原则指出“软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭”。

您可以实现任意数量的从 AbstractVisitor 派生的类:它对扩展开放。您不能添加新的可访问类,因为从 AbstractVisitor 派生的类将无法编译:它已关闭以供修改。

AbstractVisitor 类树遵循开放/封闭原则。AbstractVisitable 类树不遵守开放/封闭原则,因为它不能扩展。

除了如下扩展 AbstractVisitor 和 AbstractVisitable 之外,还有其他解决方案吗?

0 投票
2 回答
246 浏览

dependency-injection - 使类遵循 OCP - 将函数分解为对象

我有一门课,我一直在添加。

我突然想到这个类不是 Open-Closed,因为所有这些新特性都被添加了。所以我考虑通过将这些函数封装到 Request 对象中来关闭这个类以防止这种变化。我最终得到类似的东西:

这使得 OrderRepository 对扩展开放,对修改关闭。但是,我很快遇到了一些问题:

1.) 请求需要操作的数据是用户提供的(运行时)和依赖注入提供的。我显然不能同时满足一个构造函数。我不能这样做:

并称之为。我想要一种方法让 DI 框架为我“部分地”构造一个对象,然后让我做剩下的事情。但是,我看不到任何这样做的方法。我看到一个博客把这个概念称为“变量构造函数注入”。

2.) 我想到的下一件事是将它分成 2 个单独的类。用户将创建并填充一个 RequestContext,然后将其传递到存储库中,这将创建一个 RequestProcessor(想不出更好的名称)。我想过这样做:

这是一个很好的第一步。但是,请求处理器需要它存储的上下文的确切类型,而我在这里没有。我可以将类型字典用于类型,但这违背了 Open-Closed 的目的。所以我最终不得不做类似的事情:

这很奇怪,我通常不喜欢奇怪重复出现的模板模式。此外,用户填写上下文并要求我提出请求的想法似乎很奇怪,尽管这可能只是一个命名问题。

3.)我想摆脱以上所有,只拥有:

这还不错,但是 API 很丑。现在,这个对象的客户需要“构造”两次,就像以前一样。如果他们忘记调用 PackArgs,我必须抛出某种异常。

我可以继续,但这些是我目前遇到的最令人困惑的问题。有任何想法吗?

0 投票
7 回答
5661 浏览

java - 开闭原则和Java“final”修饰符

开闭原则指出“软件实体(类、模块、函数等)应该对扩展开放,对修改关闭”。

然而,Joshua Bloch 在他的名著《Effective Java》中给出了以下建议:“设计和记录继承,否则禁止它”,并鼓励程序员使用“final”修饰符来禁止子类化。

我认为这两个原则显然相互矛盾(我错了吗?)。您在编写代码时遵循哪个原则,为什么?您是让您的类保持打开状态,禁止对其中一些类(哪些类?)进行继承,还是尽可能使用 final 修饰符?

0 投票
4 回答
3447 浏览

design-patterns - 设计模式——抽象工厂模式和开闭原则

我是设计模式的初学者。

我正在尝试在保持开闭原则的同时使用抽象工厂模式。

请看下面的代码:

它可以成为抽象工厂模式的一个例子吗?

如果是,我该如何重构它并结合开闭原则的概念?

0 投票
1 回答
108 浏览

oop - 你喜欢 C# 中敏捷原则、模式和实践的数据访问部分(使用 SQL Server)吗

您如何看待这样的数据访问代码:

就个人而言,我对这样的代码感觉不太好(使用“is”来检测类型来决定要做什么),但作者罗伯特马丁说这没关系,因为它只在 DAL 中,所以有点违反 OCP 是可以接受。

你怎么想?

0 投票
5 回答
797 浏览

oop - 如此重要的“OCP”原理怎么会成为大规模重复代码实践的原因?

0 投票
6 回答
2862 浏览

open-closed-principle - 开放/封闭原则是个好主意吗?

这个问题与 OCP 是什么无关。我也不是在寻找简单的答案。

所以,这就是我问这个的原因。OCP 在 80 年代后期首次被描述。它反映了当时的思想和背景。令人担忧的是,在代码已经测试并投入生产之后,更改源代码以添加或修改功能最终会带来太大的风险和成本。所以想法是尽可能避免更改现有的源文件,只以子类(扩展)的形式添加到代码库中。

我可能错了,但我的印象是基于网络的版本控制系统(VCS)当时并没有被广泛使用。关键是 VCS 对于管理源代码更改至关重要。

重构的想法是最近才出现的。支持自动重构操作的复杂 IDE 在当时肯定是不存在的。即使在今天,许多开发人员也没有使用可用的最佳重构工具。这里的重点是,这些现代工具允许开发人员在几秒钟内安全地更改数千行代码。

最后,今天自动化开发人员测试(单元/集成测试)的想法很普遍。有许多免费和复杂的工具支持它。但是,如果我们从不/很少更改现有代码,那么创建和维护大型自动化测试套件有什么好处呢?正如 OCP 所要求的,新代码只需要新的测试。

那么,OCP 在今天真的有意义吗?我不这么认为。相反,如果新功能不需要新类,我确实更愿意在添加新功能时更改现有代码。这样做将使代码库更简单、更小,并且更容易阅读和理解。破坏先前功能的风险将通过 VCS、重构工具和自动化测试套件进行管理。

0 投票
8 回答
295 浏览

open-closed-principle - 如果我有一个完整的应用程序单元测试套件,我还必须应用开放/封闭原则(OCP)吗?

关于 OCP 的维基百科文章说(强调我的):

... 开放/封闭原则指出“软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭”... 这在生产环境中特别有价值,其中源代码的更改可能需要代码审查、单元测试和其他此类程序来使其在产品中使用的资格遵循原则的代码在扩展时不会改变,因此不需要这样的努力

那么,如果没有自动化单元测试,我是否正确地阅读了 OCP 将是有价值的,但如果有不一定?还是维基百科的文章错了?