成语与设计模式之间的区别?


39

习惯用语和设计模式有什么区别?这些术语似乎在某处重叠。确切地,我不知道。它们可以互换吗?我什么时候应该使用什么?

是C ++习语的列表。我可以称它们为设计模式吗?

维基百科定义

将成语编程为低级设计模式

这是什么意思?什么是“低层次”的意思是在这里吗?

这个问题的灵感来自另一个问题:https : //stackoverflow.com/questions/7343531/are-the-some-design-patterns-language-dependent


实际上,区分可能很难确定(习惯用法和设计模式之间可能存在一些连续性)。但是它可能源自自然语言中的“成语”一词:en.wikipedia.org/wiki/Idiom(这实际上并不适合用法)。
Merlyn Morgan-Graham

2
这可能更适合Programmers SE。
奥利弗·查尔斯沃思

3
@Nawaz:“设计模式”是围绕语言缺陷的相对“高级”构造。“成语”是围绕语言缺陷的相对“低级”结构;)
Tristan St.

@ Nawaz- +1幽默。
詹妮弗·S

Answers:


30

习惯用语是解决一种语言怪癖的想法。我想到的一些示例是您在原始问题中链接的任何C ++惯用法。他们以固定的方式解决了该语言中的一个常见问题。

设计模式类似,因为它解决了一个常见问题。但是理想的设计模式是基于通用语言功能的,因此与语言无关。

习语和设计模式之间存在连续性,就像从低级语言到高级语言一样。

访客模式就是一个很好的例子。如果只有一种语言仅支持单个动态调度,那么我们可以将Visitor模式视为该语言的惯用法。但是有成千上万种不直接支持多重调度的语言。因此,访客模式诞生了。

还可以想到Observer模式-C#直接支持它,因此它不需要该模式的通用变通形式。

朝另一个方向发展的一个例子是OO功能(继承性,多态性等)。C不直接支持它们。如果像C这样更多的语言,那么我们可能会开发设计模式来实现v表,类型安全性等。由于许多语言都支持这些功能,因此我们将C中的任何常见解决方案称为惯用语,而不是将通用化称为解决设计模式。


2
另一个有趣的示例:流利的语法API。它们弥补了您的语言没有直接DSL支持的事实,并且跨语言边界。我不确定它是否已经升级为“设计模式”状态,并且像句法成语一样响起……
Merlyn Morgan-Graham

C#直接支持Observer模式的事实似乎表明它确实对该模式有巨大的需求,以至于它使实现方式从开发人员转移到了语言本身。
jaco0646 '18

@ jaco0646我改写了这一行,现在可能更清楚了
Merlyn Morgan-Graham

37

设计模式通常不是特定于语言的。语言习语往往取决于一种语言(或某种语言的类别)的特定特征,或解决所述一种或多种语言的特定缺陷。


+1可以用很少的单词和很少的误差来区分。
Merlyn Morgan-Graham

1
@Merlyn Morgan-Graham:您已经评论了几乎所有答案,包括问题。那么,为什么不发布完全没有错误的详细答案呢?我想知道你的想法。
Nawaz

1
@Nawaz:评论是关于其他答案的。这个已经差不多完美了。理想情况下,我希望样本中提供答案,但似乎没人能正确地回答问题。我可能也做不到,否则我会很乐意履行义务:)
Merlyn Morgan-Graham

@Nawaz:好的,我还是给了他一个机会:)
Merlyn Morgan-Graham

12

我不会在Wikipedia定义中投入太多货币。

至少习惯用法是特定于语言的,而设计模式则努力或应该努力做到与语言无关。更进一步,成语通常是提高可读性的约定,或者在有多种方法可以做某事时,它是更好的选择(出于某种技术优势)。所有这些都与思想的表达方式(清晰,冗长,简洁)有关,而与思想本身无关。

另一方面,设计模式是反复出现的想法的本质,该想法是可以用任何适合自己的语言来表达先验的想法。访客是依赖于单调度和重载的双调度的实现,并且可以在具有单调度和重载的任何语言中使用。了解该模式无助于编写更具表现力或可读性的代码,有助于解决相关问题。这没有什么惯用的,因为例如在C ++中没有规范的访客形式。


1
+1; 好答案。我倾向于相信这里的一切,除了最后一点。有些语言直接支持多重调度,因此不需要在此处存在“访问者”模式。从他们的角度来看,“模式”可能更像是一种习惯用法。从最终的高级语言来看,所有模式都可能成为习语……
Merlyn Morgan-Graham

@Merlyn重新实现一流语言功能的惯用法是什么?是谁啊
卢丹顿

这才是重点。使用该语言的用户会认为“设计模式”是一种习惯用法,因为他们的语言更酷:)
Merlyn Morgan-Graham

@Merlyn那不适合我对“成语”的使用。语言的习语是您期望一种随机,熟练的语言用户能够识别的事物;重新实现一流的功能将显得陌生且不合时宜。没有用于单一调度的C ++惯用语,仅virtual在某些地方使用,而指向成员表欺骗的手写指针看起来却很愚蠢。
Luc Danton

1
我喜欢成语的定义与“穷人的设计模式”不同,这是我的模型对待它的方式(请参阅我的回答)。它不是“这里是如何实现此目标”,而是“这里是实现此目标的正确方法”。例如,我无法想象“三巨头”会演变成一种设计模式。并且还有语法成分,例如do_something() or die "...";(从此处的其他评论中窃取)。它基于特定的语言功能,但这是使用这些功能的常用方法。它不是跨语言的,而且可能不会。
Merlyn Morgan-Graham

6

惯用语的常规英语定义。是一个短语,其接受的含义未包含在所使用的单词中。例如“雨中的猫和狗”或“牛肉在哪里?”

在编程语言中,它通常是指一种语法上的快捷方式,该快捷方式从代码本身起并不立即显而易见,但经常使用,足以使其他程序员立即意识到其含义。

Perl也许是最常用的语言。使用类似的构造:

while (<IN>) {
    print $_
}

对于经验丰富的perl程序员而言,其含义是显而易见的,但对于其他任何人来说,都是一个谜


我认为“牛肉在哪里”更是一个模因而非成语。那里可能会有另一个连续体;)一个习惯用法可能不只是简单的语言实现,因为事情可能是该习惯用法的部分实现或失败的实现-例如C ++的“三巨头”。在这种情况下,成语是“三巨头”的名称和描述。
Merlyn Morgan-Graham

2
Perl的有最好的成语-do_something() or die "arrrrgh!";
cxfx

2

习语是特定于语言的。例如,while (*dest++=*src++);是C / C ++惯用语。用Pascal或Java远程编写类似的东西是完全不可能的。在英语中使用单词“ idiom”。“你好吗?” 问候是一种习语。某些语言(例如德语和frensh)具有相同的习惯用法。但是许多其他语言不会“问”这样的问候。另一方面,(面向对象)模式通常可以适应支持继承和委托的任何语言。习惯用法可能像一行代码一样简单。设计模式总是涉及几个类。


+1。好点:A idiom might be as simple as one line of code. A design pattern always involves several classes.
Nawaz

2

我发现这篇文章正在搜索常见的C ++习惯用法,因为我最近对此已经相当深入,并且希望我的代码看起来不像我感觉的那样业余... :-P

在Perl上花费了很多时间之后,我发现该语言中的成语与自然语言(如英语或西班牙语)中的成语非常相似(我只知道两个就知道一些成语)。

我不同意成语就像“小设计模式”。我仍然不同意(尽管并非如此),习惯用法是解决语言缺陷的一种方法。

也许Luc Danton的答案最接近,但让我解释一下。我认为习惯用法是那些使用该语言的人的惯用语。通常,一种通用表达或一系列表达,尽管可能并不明显,但它们以某种方式进行操作或表达意图,这对于那些精通这些知识的人来说是有意义的。

回到Perl,也许最著名的惯用语是“ Schwartzian Transform ”,该表达式以紧凑高效的方式对数据执行排序。这不是执行这种操作的最明显方法,但是它很简洁,以前看过它的人都立即知道它在做什么。

另一个著名的例子是“ Orcish Maneuver ”,它利用了perl的true / false概念,丰富的运算符和运算符优先级。

我个人非常喜欢的一个与Orcish Maneuver有关,但我不知道它的名字:

push @{ $some_hash{$key} ||= [] }, $some_value;

确实,这并不是混淆,而是对某些事情的清晰,紧凑的表达,否则将需要花费几行代码。如果键在哈希中存在并且具有真值,则将其取消引用为数组并将$ some_value推入该数组。如果哈希元素不存在或具有错误值,则为其分配一个空数组,然后取消对该数组的引用并进行推送。

还值得注意的是,从Perl 5.14开始,此惯用法的一部分已过时- 推送现在可以直接在数组引用上操作,而无需@ {}!同样,从Perl 5.10开始,可以使用// =代替|| =,它不检查真理,而是检查确定性。


在python中:some_dict.setdefault(key, []).append(some_value)
JonasKölker2013年

0

成语的要点是跨越编程语言的一种想法或概念,这是一种做事的方式,并且在从一个方面取而代之时,它在没有太多概念重组的情况下就可以正常工作,例如低气泡排序。设计模式是一个惯用语的特定实现,或者是某种想法的扩展以适合某种语言,因此您可以使用事件侦听器惯用语的javascript设计模式。


事件监听器是一种语言功能,可实现信号/插槽(模式?)或观察者模式。在C ++中还有一些叫做惯用语的东西,根本不重要或不适合其他语言(据我所知),例如“复制和交换”惯用语。
Merlyn Morgan-Graham

Design patterns are specific implementations of an idiom?到底如何 您是否在我的问题链接中看到了C ++习惯用法?
Nawaz

0

我不确定100%,但是成语只是与某个领域有关的术语。当您说“设计模式”时,您会想到“观察者模式”,“责任链”,“访客模式”,“工厂”。这些是用于解决编程中常见问题的通用模式。在此处查看完整列表:http : //en.wikibooks.org/wiki/C++_Programming/Code/Design_Patterns


0

这是什么意思?“低级”在这里是什么意思?

我认为这不是对应用程序或应用程序组件进行建模的高级抽象方法,而是对语言语义的巧妙或普遍使用。

例如,设置一个变量,如果它的结果​​为false(通常用于有条件地设置nil变量):

var ||= some_default_value

0

这是用于处理事件的惯用法(在C#中)的示例。如果没有附加任何处理程序,则不允许触发该事件,因此习惯用法是始终先检查该事件。

因此,用于处理事件的一般习惯用法变为:

EventHandler handler = this.MyEvent;
if ( null != handler ) { handler( param1, param2 ); }

这个习惯用法特定于C#语言(尽管不是排他性的)。

但是,更一般而言,C#事件机制是可以以任何语言实现的观察者设计模式的示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.