面向对象编程中的设计模式是否暗示了面向对象范式的系统性问题?

8

可能是重复问题:
设计模式真的是语言弱点吗?

在花费多年时间阅读面向对象编程(OOP)的书籍和技术,并且最近越来越涉足函数式编程风格后,是否可以推断出设计模式是指向OOP整体存在系统性问题的指针。在面向对象编程(不要与设计混淆)的处理状态时,封装的方法导致了越来越多的模式来解决这种范例所带来的问题,这是一种根本性的缺陷吗?

我还没有得出任何结论,但我的“直觉”是OOP范例可能存在更加严重的问题。

封装的概念是否会引起比解决更多的问题。


请参见https://dev59.com/33I-5IYBdhLWcg3w-92b。 - user395760
2
在使用函数式编程语言进行编程时,是否没有遵循任何模式?我认为只是没有同样的努力去识别和记录它们。我的编程经验表明,我经常会创建相同类型的函数。这是一个有趣的问题 - 因为面向对象编程肯定没有比函数式编程更早出现。也许函数式编程的模式足够简单,以至于它们似乎是常识/不可避免的,因此没有被记录到同样的程度? - jhouse
一切都遵循一定的模式,我同意这一点,但通常它们构成了语言的基础。设计模式不同,它们是围绕语言而形成的,而不是在语言设计本身中形成的。 - WeNeedAnswers
http://blog.adaptivesoftware.biz/2009/08/lack-of-design-patterns-in-python.html 演示很好。我认为我同意他的观点。 - WeNeedAnswers
在函数式语言中,为了实现一个使用条件分支和变量赋值表达的算法,你需要一些难以理解的模式。 - Kaz
5个回答

6
一个非常好的问题,也是我之前考虑过的事情。这是我的结论和看法:
1. 面向对象编程的思想并不是没有缺陷,但提供了最完备的设计范例。如果问题域表达得当,明确定义的对象会知道自己的职责,它们可以以一种相当优雅的方式进行交互,并且紧密地类似于对象(或想法)在现实世界中的交互。
2. 为了使一些更抽象的概念具体化,面向对象编程提出了一些肯定性的声明。(例如封装,不暴露超过必要的内容以及对象负责任)
3. 像所有通用假设一样,会有例外情况,当通常是一个好主意的东西可能不适合手头特定的问题时。这也并没有得到帮助,因为面向对象编程涵盖了几乎所有的问题(不像AOP甚至更复杂的语义建模,只为特定类型的问题服务)。
4. 因此,在需要针对面向对象编程断言作出例外并远离的情况下,设计师需要一种方式来保持良好设计的界限,以便他们不会太远离被接受的设计实践。
5. 对我来说,设计模式只是一些问题的案例研究,这些问题不会受到面向对象编程核心断言的服务。除了协作和解决方案的整理,设计模式还有助于增强面向对象编程。(特别是对于新手设计师)
注: 大多数情况下,并不需要使用设计模式。必须清楚地证明使用模式的理由。我知道一些初学者尝试实现一些设计模式,仅仅是因为他们知道它们(有时候甚至不仅仅是初学者)。这是一个将正方形钉放入圆孔的问题。

不错的回答。我想指出,我特别支持面向对象编程和面向对象分析。其中一些模式已经成为语言的核心部分。例如横切关注点。如果该模式在每个应用程序中都被使用,那么它是否应该成为语言的传统并更加融合? - WeNeedAnswers
如上面某位用户在另一篇帖子中所提到的一个很好的例子,就是C#中事件的使用,它基于观察者模式。 - WeNeedAnswers
我们不是在@Mattis的评论线程中进行相同的讨论吗?哈哈。无论如何,我同意你的观点。 有些人确实认为某些模式应该成为一流的面向对象编程实践。因此,我想,任何设计模式,只要不是一种变通方法并且可以普遍应用,都有可能被纳入语言中(这就是Spring的驱动力所在吧?)。 - uncaught_exceptions
有很多框架,新书,新设计,新救世主在讲台上大声宣扬他们的解决方案。我只是有一种感觉,如果有这么多需要通过“附加”到语言“带电池”的核心来解决的问题,那么面向对象编程的原始前提是否存在根本性的问题。许多问题对于良好的设计来说是如此基本,以至于仅使用核心框架(c#,Java)越来越难以提供解决方案。 - WeNeedAnswers

1

好问题,我几周前开始对此产生了疑问,当时我更深入地学习Python和Scala。

我认为是和不是。面向对象编程(OOP)和状态封装确实存在一些内在问题,但这并不意味着OOP本身是一种不好的做事方式。我认为问题在于,当你手中只有一把锤子时,所有东西都变成了钉子。OOP非常适合某些事情,首先想到的是GUI,但函数式编程也有非常明显的优点。

值得注意的是,像Scala这样的新型函数式编程语言并没有放弃对象。

我没有深入思考这个问题,但我肯定同意OOP存在一些问题,除了设计模式之外,我还没有看到其他解决方法,而设计模式实际上是在解决症状而不是疾病。


我是面向对象编程(OOP)的狂热支持者,但偶尔会感到困惑,觉得似乎有什么东西我无法理解。我希望有人能指出我未能领悟到的问题所在。上周我参加了一个会议,他们滔滔不绝地谈论Ioc和控制反转容器,我也有同样的感觉。 - WeNeedAnswers
@WeNeedAnswers,我认为问题是寻找“银弹”。 没有单一的解决方案,只有某些解决方案比其他解决方案更适用。 (而IOC只是面向对象编程中的一个模式,它可能是实现良好设计的最简单方法之一) - uncaught_exceptions
一个好的设计或者是对范例中问题的一种解决方法? - WeNeedAnswers
我不同意,这不是一个变通方法。面向对象编程并不涉及如何实例化对象。控制反转只是一种实现细节。它说,如果你可以在对象本身不参与的情况下管理对象之间的交互,那么你将得到一个更松散耦合、更易于测试的应用程序。 - uncaught_exceptions
如果有一个类比,好的设计就像对程序员说,“热爱你所做的,其他的自然会随之而来”。但在某些情况下,引入新的术语/方法可能会使我们重新审视以前的断言。例如,当我们开始使用RMIs时,我们发现网络延迟是一个问题,不想要一个啰嗦的系统。这时候就需要引入会话外观模式(顺便说一句,我讨厌它)。这只是一个简单的解决方法。 - uncaught_exceptions
显示剩余3条评论

1

不是的。虽然你会看到略有不同的设计模式,但在函数式代码中仍然可以看到设计模式。基本区别与缺乏状态无关,而主要源于(大多数)函数式语言在创建函数方面提供了足够的灵活性,因此在其他语言中可能成为“设计模式”的东西在函数式语言中只是一个函数。

如果您在具有状态的语言中提供了(大致)相似的灵活性,则可以获得相同的效果。例如,现代C++设计的大部分介绍都在捍卫一种观点,即设计模式可以编码为模板(该书的大部分内容都是实现为模板的设计模式)。


2
@WeNeedAnswers:问题不在于面向对象编程,而在于编程语言本身。 - Jerry Coffin
在面向对象编程的实现方面或多范式支持的缺乏方面有何看法? - WeNeedAnswers
@WeNeedAnswers:我不确定它真的属于哪个类别。 - Jerry Coffin
你能给我一个类别吗?也许这就是我缺少的东西。 :) - WeNeedAnswers
模板可以满足一些设计模式,但并不适用于其他一些模式。即使是“扩展”版本也只能满足更多当前设计模式,而我们仍然会发现这些模式在更大的范围内出现。 - Jerry Coffin
显示剩余3条评论

0
我认为,当你尝试将单一的编程范式应用于一个问题时,难免会出现问题。这就是为什么我喜欢 C++:它是多范式的;它不会强制你使用一套固定的解决方案。

这对C#和Java用户来说是个坏消息,他们被迫通过语言构造进入一种范式。有关多范式语言的评论很有趣。 - WeNeedAnswers
你总是可以“打破”那些语言的限制。例如,在C#中,如果你非常想让它看起来更像C语言,你可以创建一个大而全的静态方法类。 - Reinderien
不,我认为如果你要使用这些语言之一,我认为你必须发挥该语言的优势。C#和Java在大多数方面都是优秀的语言。但是偶尔会出现一些问题......当我使用Delphi时,我从未遇到过这些相同的问题,也许这是简单时代的标志,或者正如你所指出的,多范式是有用的。 - WeNeedAnswers
我并没有说破解语言是一个好主意,只是说这是可能的。 - Reinderien

0

我在重复我的一个基本理论,即模型只是模型。面向对象编程(OOP)定义的模型是一种非常有效的程序结构方式,并且对于许多应用程序编程领域来说,它完全合适。对于某些问题领域,该模型可能会变得越来越不有效(或者效率较低,或者两者都有)。

物理学存在一个潜在的比喻。许多年来,牛顿力学在模拟运动、时间和空间定律方面做了(实际上仍然在做)出色的工作(在欧几里得几何和球面几何的帮助下)。但当科学开始探索问题领域的微观和宏观方面时,牛顿力学(以及欧几里得/球面几何学)开始崩溃。因此,我们现在有了相对论和量子力学。它们分别可以很好地模拟宏观和微观水平上的宇宙,但对于日常人类规模的事件描述来说过于复杂。

在很多情况下,面向对象编程非常有效,特别是考虑到建模现实世界问题和人类交互以被线性机器消费和处理所涉及的复杂性时。正如某些人观察到的那样,没有银弹。我的印象(从未使用过C++)是,试图成为多范式的语言也会变得更加复杂,并且不一定对更容易使用高级、更有针对性的语言处理的小问题更有效。就像量子力学和/或相对论理论一样(我是说,真的吗,在高速公路上以60英里每小时的速度行驶时,有人关心质量和速度之间的关系吗?或者洛杉矶在你到达时是否在预期位置上的概率?)。
在我看来,遵循特定模型的规定对于问题空间而言非常重要,只要该模型适用于该问题空间。当这一点不再成立时,该模型可能需要发展,而对此将会有阻力。会有试图将问题空间强制转换为不适合的模型(再次查看物理学的历史,或者了解太阳系日心说模型的演变,包括关键词“表轮”)。
以上所有内容仅仅是我对事物状况的最好理解,如果我在某个地方没有抓住要点,我很乐意听到一些相反的消息。

关于我的C++评论,我使用“高效”一词是指更高级别的语言可能更容易用于解决问题,而不是说C#或VB在性能方面更有效率。当然,最有效率的语言是自己熟悉的语言。但从我所知道的C++来看,将其应用于解决企业环境中中型IT部门面临的日常业务问题将是过度杀伤力(例如)。 - XIVSolutions
我认为OOA和OOP应该有所区分。我同意OOA从未让我失望过,当然,掌握模式的OOP也是如此。但是问题来了,似乎有越来越多的模式,如果这些模式中只有三分之一对于使OOP工作至关重要,那么OOP是否存在缺陷?如果是这样,我们能否解决它。如果我们知道缺陷在哪里,那么所有的模式都将得到解决,或许需要一种新的语言、新的范例等等。 - WeNeedAnswers
我认为设计模式是表达特定情况下面向对象编程实现的非常有用的方式。如果你认为面向对象编程类比于几何学,那么面向对象编程的核心原则就类比于该学科的公理和定理。而设计模式可能类比于推导出几何结构的各种定理。请注意,即使在特定几何形状失败的地方,这个比喻也成立。经典欧几里得几何很好地工作,直到遇到球面为止。 - XIVSolutions
在这一点上,模型开始失效。虽然你可以强制欧几里得几何的规则来近似圆形表面上的相同形状,但是模型最终会无处可去,需要一个新的、有些专门的模型。当将概念应用于球面时,必须重新定义直线的性质。 - XIVSolutions
我认为设计模式是面向对象编程在特定情况下的表达。你会注意到有些模式经常被使用,而有些则偶尔才出现。但对我来说,新模式的演变并不意味着面向对象编程作为一种实践存在缺陷。只是因为有许多问题空间需要有人在某处定义一个新模式作为解决方案。设计模式也可以类比于方程式。大多数函数有很多表达方式,但通常只有一种最简单的方式。 - XIVSolutions

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接