问题标签 [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 投票
2 回答
2208 浏览

java - DAO 模式和开闭原则

我已经看到并使用过很多旧的、基于 JDBC 的 DAO 代码,这些代码通常从 CRUD 方法开始。我的问题特别与检索方法或“发现者”有关。通常,我发现 DAO 以两种方法开始:

  • 查找并返回所有
  • 根据唯一标识符检索特定实例

通常,这两个发现者是不够的。我通常最终会看到一个 DAO 类被反复修改以添加 finder 方法,如下所示:

  • 查找并返回 ALL where {condition}

发生的情况是,当需要支持新的 {conditions} 或修改现有方法以添加新参数作为标志以修改方法内部的 SQL 查询以支持附加条件时,会添加更多方法。

这是一种丑陋的方法,违反了开闭原则。每当需要支持一些新的检索条件时,看到 DAO 类不断修改,这一直是我的烦恼。对这个问题的研究经常将我指向存储库模式并将检索条件封装为规范或查询对象,然后将它们传递给查找器方法。但这似乎只有在您拥有整个数据集的内存集合或使用某种 ORM 时才可行(我正在使用较旧的 JDBC 代码)

我考虑过一种解决方案,该解决方案将 DAO 管理的整个数据集作为内存中的集合延迟加载,然后使用规范模式作为检索查询。然后我在集合上实现某种观察者,它在调用创建、更新或删除方法时只更新数据库。但显然性能和可扩展性会受到严重影响。

对此有什么想法吗?


感谢您到目前为止的回复。我确实有一个想法——您对使用命令/策略模式来封装数据访问请求有何看法?每个单独的具体命令可以代表一种特定类型的访问,并且可以传递给调用者。我最终会得到许多具体命令类,但每个类都将只关注一种访问,并且应该非常可测试和隔离。

0 投票
1 回答
4830 浏览

c# - 了解开闭原则

当我遇到以下代码时, 我正在重构一个简单的脚本文件解析器的一些旧代码:

这个简单的脚本处理器在我看来是通过应用“开放封闭原则”进行重构的一个很好的候选者。以 a 开头的行$可能永远不会有不同的处理方式。但是,如果!需要添加以 a 开头的新指令怎么办?还是需要新的处理标识符(例如新的 switch-case)?

问题是,我无法弄清楚如何在不破坏 OCP 的情况下轻松正确地添加更多指令和处理器。!使用scope 和/或 的-caseline使它有点棘手,就像default-case 一样。

有什么建议么?

0 投票
2 回答
379 浏览

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

根据Open/Closed原则

. . . 软件实体(类、模块、函数等)应该对扩展开放,对修改关闭

那么我可以说Category严重违反了这个原则吗?

0 投票
3 回答
186 浏览

design-patterns - 打开/关闭灵活的软件

标题可能不太具有描述性,但我想不出更好的标题。我很抱歉。

所以,我在这里遇到的问题是我现在遇到过几次的问题。它实际上与设计模式和原则有关,只要您的语言中有 OO 工具,它就与语言无关。我将带您了解当前遇到的问题,因为如果没有实际示例,很难解释问题所在。

所以,我在这里使用一些类来描述逻辑语句。想想这样的事情:

现在这一切都是花花公子,但是当我想使用这个类系统时问题就来了。现在,我正在制作一个需要将条件转换为 SQL WHERE 子句的系统。

我可以通过多种方式做到这一点,但似乎都没有遵守开放/封闭原则。例如,我可以让Database类解析条件并将其设为 SQL。问题是,通过这种方式,我无法Condition在不需要更改 my 的情况下扩展 my Database,因此我们没有遵循 Open/Closed。

另一种方法——在这里看起来很合乎逻辑——是在toSQL()my s.s 中添加一个函数Condition。但是,在这种情况下,我无法将我的数据库换成一个(只是为了命名)使用 XML 的数据库,它不希望 SQL 格式的条件。

我过去解决这个问题的一种方法是使用工厂。在这种情况下,工厂方法看起来像这样:

这不是那么好,但它会减少对打开/关闭的违反。

现在,您可以很好地继承您的数据库。你也只需要对你的工厂进行子类化,并且你还必须为你的工厂创建一堆新的ConditionDatabase。你也可以在 Condition 类上发挥你的魔力。您可以创建一个新Condition的 s,但您也必须为每个创建伴随类Database。最后,您将不得不修改您的工厂。

这是迄今为止我们看到的最小的违规行为,但我们仍然违反了 Open/Closed。但事实上,我宁愿完全不违反它。有没有办法在坚持打开/关闭的同时做到这一点?

0 投票
2 回答
264 浏览

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

考虑以下代码

这是开放/封闭原则吗?即,将大部分责任交给基类,并允许继承类的某些功能责任。

感觉不像,所以如果不是开闭原则,那这是一种什么样的设计模式?

干杯

0 投票
3 回答
497 浏览

php - 创建对象时如何应用开闭原则

我正忙于解析 xml 文档(google docs api)并将单个文档放入对象中。

有不同类型的文档(文档、电子表格、演示文稿)。关于这些文件的大部分信息是相同的,但有些是不同的。

这个想法是创建一个包含所有共享信息的基本文档类,同时为每个特定的文档类型使用子类。

问题是为不同类型创建正确的类。有两种方法可以区分文档的类型。每个条目都有一个类别元素,我可以在其中找到类型。将使用的另一种方法是由 resourceId 使用,格式为type:id.

最天真的选择是创建一个 if 语句(或 switch 语句)检查条目的类型,并为其创建相应的对象。但是,如果要添加新类型,则需要编辑代码。

现在我不确定是否有另一种方法来解决这个问题,所以这就是我在这里问它的原因。我可以将创建正确类型的对象封装在工厂方法中,因此所需的更改量很小。

现在,我有这样的事情:

所以我的问题是,是否有另一种我看不到的方法来处理这种情况?

编辑: 添加示例代码

0 投票
4 回答
4309 浏览

c# - 开/关原则——如何处理这个开关?

我一直在研究开放封闭原则,听起来不错,所以我想练习它的教义。我看着将我新发现的知识应用到现有项目中,并立即变得有点卡住了。

如果出现一个新的 UserType(这很可能),这将需要更改,它还没有关闭修改。怎么能绕过这个?

根据我的阅读,听起来我应该在这里实现工厂而不是应用 OCP?

打破开闭原则的工厂

谢谢,科汉

0 投票
3 回答
1362 浏览

oop - 开源库中 OCP 的好例子

关于stackoverflow上的“开闭原则”这个话题已经有很多讨论了。然而,一般来说,对原理的更宽松的解释似乎很普遍,因此例如 Eclipse 是开放的,可以通过插件进行修改。

根据严格的 OCP,您应该只修改原始代码以修复错误,而不是添加新行为。

在公共或 OS 库中是否有任何严格解释 OCP 的好例子,您可以在其中通过 OCP 观察功能的演变:有一个带有方法 bar() 的类 Foo,然后有一个带有 foo2() 方法的 FooDoingAlsoX库的下一个版本,其中原始类已在未修改原始代码的情况下进行了扩展。

编辑:根据 Robert C. Martin 的说法:“模块的二进制可执行版本,无论是可链接库、DLL 还是 Java .jar 都保持不变”*。我从来没有看到图书馆保持关闭,实际上新行为被添加到图书馆并发布了新版本。根据 OCP,新行为属于新的二进制模块。

*Robert C. Martin 的敏捷软件开发、原则、模式和实践

0 投票
2 回答
1582 浏览

liskov-substitution-principle - 了解 Liskov 和 OCP 之间的关系

我正在巩固我对 Liskov Substitutional Principal 和 Open Close Principal 之间关系的理解。如果有人能证实我的推论并回答我下面的问题,那就太好了。

我有以下课程。如您所见,B它派生自A并覆盖该DisplayMessage函数以改变行为。

现在在我的引导程序中,ShowClassTypeis期待一个类型的对象,A它应该有助于写出它是什么类类型。然而B,它违反了 LSP,所以当它的DisplayMessage函数被调用时,它会打印一条完全出乎意料的消息,并且本质上会干扰ShowClassType.

所以我的问题是,我的结论是否正确,ShowClassType因为现在 B 型可以进入并更改该方法的预期功能,它不再关闭以进行修改(即确保它保持它的预期的行为,你必须改变它,以便它首先检查以确保我们只使用原始 A 对象)?

或者,相反,这只是一个很好的例子来表明它ShowClassType是封闭的,并且通过传入派生类型(尽管 LSP 违反了)我们已经扩展了它的意图?

最后,如果基类不是抽象的,在基类上创建虚函数是不好的做法吗?通过这样做,我们不只是在邀请派生类违反 Liskov Substitution 原则吗?

干杯

0 投票
2 回答
925 浏览

unit-testing - 测试驱动开发和开放/封闭原则如何协同工作?

我一直在阅读单元测试、TDD 和 SOLID 原则,我需要一些说明。我的理解是,如果坚持开放/封闭原则,由于代码对修改是封闭的这一事实,单元测试可能在很大程度上变得不必要——因此如果代码被正确隔离和解耦,则无需重新测试。如果代码一旦通过相关的单元测试就不会改变,那么单元测试增加的前期成本的长期利益就会丧失。代码将永远通过,因为它永远不会改变,对吧?继承的类需要测试,但是一旦通过了相关测试,它们也将被关闭修改,不需要重新测试。维基百科关于 OCP 的文章在第一段中强化了这一思路,(我意识到这并没有成为法律)。
我发现 OCP 和 TDD 和谐共存的最佳解释是在这里,尽管 Arnon 似乎是在说 OCP 是对 TDD 的补充,因为不鼓励开发人员修改源代码,因为现有的测试方法在修改以测试新方法时会变得复杂功能。
这就是它的全部吗?请注意,我不是在寻找争论,我是新手,我正在寻找比我更有经验的人的澄清。