Collections.sort 使用啥设计模式?

Posted

技术标签:

【中文标题】Collections.sort 使用啥设计模式?【英文标题】:What design pattern does Collections.sort use?Collections.sort 使用什么设计模式? 【发布时间】:2017-07-15 11:37:54 【问题描述】:

当以下列方式将比较器应用到列表时,所使用的设计模式或此处使用的技术是什么?

Collections.sort(myCollection, new Comparator<MyItem>() 

    @Override
    public int compare(MyItem item1, MyItem item2) 
        return item1.getId().compareTo(item2.getId());
    

);

【问题讨论】:

Strategy. @AndyTurner 我不认为有任何 design-pattern 被她使用。这是您的常规等级多态性。您共享的链接定义了 Strategy Pattern 的 structure 与 interface 和一些具体实现。 @CKing 你能想到一种行为设计模式,它不是“你的常规级多态性在行动”吗? @AndyTurner 设计模式建立在多态性继承等概念之上。 策略模式 具有明确定义的结构。 Strategy Patternpolymorphism 这两个术语不能互换。 @AndyTurner Eric Gamma 在谈到策略模式时说对象组合提供了一种潜在的更可行和更灵活的扩展机制。对象组合是定义策略模式的关键。我希望我能同意不同意,但我不能,因为在 多态性 和策略模式方面存在微妙但明显的区别。模式使用语言提供的基本构建块。它不能与这些块互换。 【参考方案1】:

TL;DR

Collections.sort 是一个简单的多态替换示例,无论您使用函数式编程 还是面向对象编程 来进行此替换。 策略模式这个术语不能与多态性函数式编程互换。

我们仍然可以说我们将排序Strategy 传递给sort 方法,但没有Context,它不是策略模式的同义词。


当以下列方式将比较器应用到列表时,所使用的设计模式或此处使用的技术是什么?

由于此问题已被标记为 OOP,因此此处本身没有使用 OOP design-pattern。这是一个普通的旧多态。一些程序员可能将其称为策略模式,但我不同意。 Strategy 模式提倡 Composition 而不是 Inheritiance,您使用 has-a 关系而不是 is -a 关系。

一些程序员可能会进一步争辩说,我们将排序Strategy 传递给Collections.sort 方法,所以这是策略模式;然而,需要承认的是Strategy策略模式的组成部分之一。 Strategy 模式的另一个重要组成部分是它的Context,它与Strategy 建立HAS-A 关系。这个组件是 Strategy Pattern 背后动机的核心,它更喜欢 composition 而不是 inheritance。你不能从整体中取出一个部分,仍然把那个分离的部分称为一个整体。您不能将Context策略模式 中取出,而仍将其余部分称为策略模式

Collections.sort 是一个static 方法,它允许您多态替换Comparator 实现以在运行时使用。


支持材料

我们来看看GoF中策略模式的定义:

将算法封装在对象中是 Strategy 的意图 (315) 模式。该模式的主要参与者是策略 对象(封装了不同的算法)和上下文 他们经营的。合成器是策略;它们封装了不同的格式化算法。 合成是合成策略的上下文

....

对象组合提供了一种可能更加可行和灵活的扩展机制..

现在应该清楚多态策略模式之间存在细微差别。 Strategy 模式讨论了一个使用 compositionContext,如上面 bold 中突出显示的那样。 Collections 类没有与 Comparator 建立 composition 关系。此外,Strategy Pattern 的 class diagram 显示了一个名为 Context 的组件,它构成了 Strategy 接口。

这个问题被标记为OOP,但是如果我们想讨论Collections.sort 在函数式编程范式中代表什么模式,我会说它代表函数式编程。 (如果我必须将函数传递给方法等同于 OOP 模式,我会说它更接近(不完全)类似于 Command 模式 而不是 Strategy 模式

相关内容:Does Functional Programming Replace GoF Design Patterns?

【讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 最简洁的陈述在第 316 页,“策略提供了一种配置类的方法...”如果策略提供了一种配置方法的方法,那么本书将这样说的。 (在解读GoF时,我倾向于textualism的视角。)【参考方案2】:

我认为先看看另一种形式会更好

Collections.sort(myCollection)

在运行时没有任何算法来比较项目。在这种方法中,它使用由 Items 继承提供的算法(通过实现 Comparable 接口)。不是直截了当,但如果我们稍微灵活一点,这就是模板模式。这种方法使用继承并且项目的行为不能在运行时改变。

但在第二种形式

Collections.sort(myCollection, 比较算法)

与模板模式(继承)不同,我们在运行时发送行为,当我们使用运行时提供的可变行为时,这是可能的。这是策略模式中最重要的部分。

可能有人会问Strategy Pattern的Composition部分在哪里?组合不仅仅是为了保存算法,以便在需要时使用它。但是在这种情况下,每当需要算法时,它都会作为参数传递,因为 Collections 类是用于不同目的的 Utils 类,而不是我们在原始版本的策略模式中看到的 Context 类。

【讨论】:

动态调度和运行时多态性是每个面向对象语言的成熟特性/结构。面向对象的设计模式建立在这些语言特性/结构之上。说动态调度就像模板模式或方法参数中的多态替换与策略模式一样是适得其反和违反直觉的。设计模式的优势在于它们的交流。如果我们开始将每个语言特征/结构等同于设计模式,我们就会造成混乱并使这些模式变得毫无用处。【参考方案3】:

Collections.sort() 使用Strategy 模式。

【讨论】:

我不同意。策略模式有一个明确定义的结构,Collection.sort 没有使用。策略模式提倡组合而不是继承。 策略模式多态是不可互换的术语。

以上是关于Collections.sort 使用啥设计模式?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Collections.sort 使用合并排序而不是快速排序?

java中排序函数sort()使用,Arrays.sort()和Collections.sort()

关于Java中Collections.sort和Arrays.sort的稳定性问题

使用 Collections.sort 时出错

jdk8 Collections#sort究竟做了什么

jdk8 Collections#sort究竟做了什么