- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
stackoverflow 上有很多关于“开闭原则”主题的讨论。然而,似乎普遍对原理有更宽松的解释,例如 Eclipse 是开放的,可以通过插件进行修改。
根据严格的 OCP,您应该仅修改原始代码来修复错误,而不是添加新行为。
在公共(public)或操作系统库中是否有严格解释 OCP 的好例子,您可以在其中通过 OCP 观察功能的演变:有一个带有方法 bar() 的类 Foo,并且有一个带有 foo2() 的 FooDoingAlsoX库的下一版本中的方法,其中原始类已扩展,原始代码未修改。
编辑:根据 Robert C. Martin 的说法:“模块的二进制可执行版本,无论是可链接库、DLL 还是 Java .jar 都保持不变”*。我从未见过图书馆关闭,实际上,新行为被添加到图书馆并发布新版本。根据OCP,新的行为属于新的二进制模块。
*Robert C. Martin 的《敏捷软件开发、原则、模式和实践》
最佳答案
OCP 原则规定,类应对扩展开放,但对更改关闭。实现这一点的关键是抽象。如果你还读过 DIP 原理,你会发现抽象不应该依赖于细节,而细节应该依赖于抽象。在您的示例中,您的界面中有详细信息(两个特定方法 bar() 和 foo2())。要完全实现 OCP,您应尽量避免此类细节(例如,尝试将它们移至抽象后面,而采用一种具有不同实现的通用 foo 方法)。
例如,看看 SolrNet 中的这个接口(interface): https://github.com/mausch/SolrNet/blob/master/SolrNet/ISolrCommand.cs这是一个通用命令,仅告诉您可以执行某个命令,并没有提供更多详细信息。
细节在于接口(interface)的实现: https://github.com/mausch/SolrNet/tree/master/SolrNet/Commands
如您所见,您可以添加任意数量的命令,而无需更改任何其他类的实现。具体实现可以认为是封闭的修改,但接口(interface)允许我们使用新命令扩展功能,因此开放扩展。
(无论如何,SolrNet 并不是特别出色,我只是使用了这个项目中的示例,因为当我阅读这篇文章时,我的浏览器中碰巧有它,几乎所有良好编码的 OO 项目都以一种方式利用 OCP 原则,或者另一个)
编辑:如果您想要二进制级别的示例,您可以查看 nopCommerce (http://nopcommerce.codeplex.com/releases/view/69081),例如您可以在其中添加自己的运输提供商、支付提供商或汇率提供商,甚至无需通过实现一组接口(interface)来触及原始 DLL。再说一次,这对于 nopCommerce 来说并不是什么特别的事情,这只是我想到的第一个项目,因为我几天前使用过它;)
OCP 并不是一个只能在二进制级别使用的原则,好的 OOD 使用 OCP,不是在任何地方,而是在所有适合的级别;)二进制级别上的“严格”OCP 并不总是合适,并且如果您在每种情况下都使用它,则会增加额外的复杂性,当您想要在运行时更改实现或当您希望让外部开发人员能够扩展您的接口(interface)时,它最有趣。在设计界面时,您应始终牢记 OCP 原则,但不应将其视为法律,而应将其视为应在正确情况下使用的原则。
我猜当您引用 Robert C Martin 时,您指的是敏捷原则、模式和实践,如果是这样,请阅读同一章中的结论,他所说的内容与我上面所做的相同。例如,如果您阅读他的《Clean Code》一书,他对 OCP 原理给出了更详细的解释,我想说上面的引用有点不幸,因为它会让人们认为您应该始终将新代码放入新的 DLL:s、JAR 中:s 或 libs,事实是您应该始终考虑上下文。
我认为您应该看看 Martins 关于 OCP 的最新白皮书 http://objectmentor.com/resources/articles/ocp.pdf (他在后来的《清洁代码》一书中也提到了这一点),在那里他从不引用单独的二进制文件,而是引用“类、模块、函数”。我认为这证明了Martin在谈论OCP时不仅仅指的是二进制扩展,还指的是类和函数的扩展,因此二进制扩展并不比我第一个示例中的类扩展更“严格”。
关于oop - 开源库中 OCP 的好例子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7222585/
谁能给我一个关于如何使用函数 crypt_r() 的例子吗? 在手册页中,不清楚返回的 char * 字符串是指向函数本身内部(在堆中)分配的内存块,还是仍然指向静态内存,如 crypt()? 最佳答
在 Spectre 中paper ,有一个利用越界数组访问的示例(第 1.2 节)。代码是 if (x < array1_size) y = array2[ array1[x] * 256 ];
这是 Grammar: difference between a top down and bottom up? 的后续问题 我从这个问题中了解到: 语法本身不是自上而下或自下而上的,而是解析器 有些
在java的构造函数中声明变量合法吗?示例。 Time(){ long timeMill = System.currentTimeMillis(); int secon
我一直在仔细研究 slick grid 的示例,并且想要 ping SO 社区并查询 Excel 电子表格编辑演示的示例?就存储而言,网格仅存储整数数据,并且网格将托管在 mvc3 razor 页面内
我很难将愚蠢的菜单置于我网站页面的中心。我知道我可以将外部 div 的宽度设置为 px 值,但我怎样才能让它以响应式网站为中心?这是页面: http://103.4.17.225/~america/i
我正在寻找可在 wordpress 上使用的主题。有时,页面会在调整大小的网络浏览器上正确加载,但在移动设备上却不能,即使尺寸相同,它也会加载某种错误(通常是错位)。例如,在此页面中 ( http:/
union { unsigned char raw[8]; struct { uint8_t gz_method; uint8_t flag;
我想使用 matchShapes() 函数在查询图像中查找对象。 假设我有一本书的模型图像,我想提取它的形状,然后尝试在另一幅图像中找到这本书(它的形状)。 我在谷歌上搜索了很多,但找不到任何关于如何
我正在寻找一个使用 inotify 的简单、简洁的示例gem 来检测目录的更改。 它缺少示例。 最佳答案 examples/watcher.rb 中有一个示例.该链接指向 aredridel 的 re
我一直在努力学习编程中的递归是什么,我需要有人来确认我是否已经完全理解它是什么。 我尝试考虑的方式是通过对象之间的碰撞检测。 假设我们有一个函数。当确定发生碰撞时调用该函数,并使用对象列表调用它以确定
我正在尝试学习如何在我正在处理的项目中使用 jBullet,我已经查看了源提供的演示,但我只是无法弄清楚这些演示如何显示对象。谁有好的资源可以指点我或提供一个在屏幕上显示一个或两个对象的基本示例? 在
我想在一个简单的 x,y 图表上绘制线条,以使用 JGraphT 在 JApplet 中显示。我找到的例子不是很有帮助。有人可以给我指出一些简单的 JGraphT 示例吗? 最佳答案 这里有一个例子,
在解决几何问题时,我遇到了一种称为滑动窗口算法的方法。 真的找不到任何关于它的学习 Material /细节。 算法是关于什么的? 最佳答案 我认为它更像是一种技术而不是一种算法。这是一种可用于各种算
我正在学习同步方法,以防止 Java 中的竞争条件和不良行为。我看到了以下示例,并被告知竞争条件非常微妙: public class Messages { private String messa
我有 100 万个 pdf,如何使用 hadoop 转换为文本并将其用于分析。目标是利用 hadoop 的强大功能将 pdf 数据提取为文本。 最佳答案 我已经在 Hadoop 上处理了一个 pdf
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我读到过,由于堆栈展开,从析构函数中抛出不是一个好主意。我不确定我是否完全理解。所以我尝试了下面的例子 struct foo { ~foo() { throw 1;
任何人都可以告诉我一个简单的(代码)示例来展示 response.encodeURL() 的用法吗?我所有的搜索(包括 google 和 stackoverflow)只提供了 encodeURL()
我受困于 haskell 类型。 {-# LANGUAGE OverloadedStrings #-} module Main ( main ) where import qualified
我是一名优秀的程序员,十分优秀!