问题标签 [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.
oop - 开放/封闭原则背后的含义和推理是什么?
开放/封闭原则指出软件实体(类、模块等)应该对扩展开放,但对修改关闭。这是什么意思,为什么它是良好的面向对象设计的重要原则?
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 编程。
对此的任何意见将不胜感激。
dependency-injection - 使类遵循 OCP - 将函数分解为对象
我有一门课,我一直在添加。
我突然想到这个类不是 Open-Closed,因为所有这些新特性都被添加了。所以我考虑通过将这些函数封装到 Request 对象中来关闭这个类以防止这种变化。我最终得到类似的东西:
这使得 OrderRepository 对扩展开放,对修改关闭。但是,我很快遇到了一些问题:
1.) 请求需要操作的数据是用户提供的(运行时)和依赖注入提供的。我显然不能同时满足一个构造函数。我不能这样做:
并称之为。我想要一种方法让 DI 框架为我“部分地”构造一个对象,然后让我做剩下的事情。但是,我看不到任何这样做的方法。我看到一个博客把这个概念称为“变量构造函数注入”。
2.) 我想到的下一件事是将它分成 2 个单独的类。用户将创建并填充一个 RequestContext,然后将其传递到存储库中,这将创建一个 RequestProcessor(想不出更好的名称)。我想过这样做:
这是一个很好的第一步。但是,请求处理器需要它存储的上下文的确切类型,而我在这里没有。我可以将类型字典用于类型,但这违背了 Open-Closed 的目的。所以我最终不得不做类似的事情:
这很奇怪,我通常不喜欢奇怪重复出现的模板模式。此外,用户填写上下文并要求我提出请求的想法似乎很奇怪,尽管这可能只是一个命名问题。
3.)我想摆脱以上所有,只拥有:
这还不错,但是 API 很丑。现在,这个对象的客户需要“构造”两次,就像以前一样。如果他们忘记调用 PackArgs,我必须抛出某种异常。
我可以继续,但这些是我目前遇到的最令人困惑的问题。有任何想法吗?
java - 开闭原则和Java“final”修饰符
开闭原则指出“软件实体(类、模块、函数等)应该对扩展开放,对修改关闭”。
然而,Joshua Bloch 在他的名著《Effective Java》中给出了以下建议:“设计和记录继承,否则禁止它”,并鼓励程序员使用“final”修饰符来禁止子类化。
我认为这两个原则显然相互矛盾(我错了吗?)。您在编写代码时遵循哪个原则,为什么?您是让您的类保持打开状态,禁止对其中一些类(哪些类?)进行继承,还是尽可能使用 final 修饰符?
design-patterns - 设计模式——抽象工厂模式和开闭原则
我是设计模式的初学者。
我正在尝试在保持开闭原则的同时使用抽象工厂模式。
请看下面的代码:
它可以成为抽象工厂模式的一个例子吗?
如果是,我该如何重构它并结合开闭原则的概念?
oop - 你喜欢 C# 中敏捷原则、模式和实践的数据访问部分(使用 SQL Server)吗
您如何看待这样的数据访问代码:
就个人而言,我对这样的代码感觉不太好(使用“is”来检测类型来决定要做什么),但作者罗伯特马丁说这没关系,因为它只在 DAL 中,所以有点违反 OCP 是可以接受。
你怎么想?
open-closed-principle - 开放/封闭原则是个好主意吗?
这个问题与 OCP 是什么无关。我也不是在寻找简单的答案。
所以,这就是我问这个的原因。OCP 在 80 年代后期首次被描述。它反映了当时的思想和背景。令人担忧的是,在代码已经测试并投入生产之后,更改源代码以添加或修改功能最终会带来太大的风险和成本。所以想法是尽可能避免更改现有的源文件,只以子类(扩展)的形式添加到代码库中。
我可能错了,但我的印象是基于网络的版本控制系统(VCS)当时并没有被广泛使用。关键是 VCS 对于管理源代码更改至关重要。
重构的想法是最近才出现的。支持自动重构操作的复杂 IDE 在当时肯定是不存在的。即使在今天,许多开发人员也没有使用可用的最佳重构工具。这里的重点是,这些现代工具允许开发人员在几秒钟内安全地更改数千行代码。
最后,今天自动化开发人员测试(单元/集成测试)的想法很普遍。有许多免费和复杂的工具支持它。但是,如果我们从不/很少更改现有代码,那么创建和维护大型自动化测试套件有什么好处呢?正如 OCP 所要求的,新代码只需要新的测试。
那么,OCP 在今天真的有意义吗?我不这么认为。相反,如果新功能不需要新类,我确实更愿意在添加新功能时更改现有代码。这样做将使代码库更简单、更小,并且更容易阅读和理解。破坏先前功能的风险将通过 VCS、重构工具和自动化测试套件进行管理。
open-closed-principle - 如果我有一个完整的应用程序单元测试套件,我还必须应用开放/封闭原则(OCP)吗?
关于 OCP 的维基百科文章说(强调我的):
... 开放/封闭原则指出“软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭”... 这在生产环境中特别有价值,其中源代码的更改可能需要代码审查、单元测试和其他此类程序来使其在产品中使用的资格:遵循原则的代码在扩展时不会改变,因此不需要这样的努力。
那么,如果没有自动化单元测试,我是否正确地阅读了 OCP 将是有价值的,但如果有则不一定?还是维基百科的文章错了?