设计模式:原型

2025-06-10

设计模式:原型

原型?

你可能会想到这一点:

替代文本

或者甚至是这样的:

替代文本

我很想写一篇关于 Prototype 这款游戏有多棒的文章。可惜我们系列文章是设计模式。所以我们就不多说了,先来聊聊Prototype设计模式。

今天你将学习:

  • 原型模式的核心概念。
  • 原型模式的简单实现。
  • 使用原型模式的机会。
  • 原型模式的优缺点。

定义

替代文本

原型模式是一种创建型设计模式,它允许我们克隆对象而不必依赖于其底层类。

但是我们为什么要克隆对象呢?

嗯,在某些情况下你可能需要克隆一个对象:

  • 懒惰:创建新对象可能很麻烦,你可能需要向构造函数传递一些参数,或者调用一些方法来设置某些字段。有时,直接克隆一个你想要的对象会更简单。
  • 业务逻辑:有时,业务逻辑只需要克隆对象。例如,您正在开发一个地图应用,该应用会帮您找到使用汽车从 A 到 B 的最佳路径。程序可能会克隆该Car对象,然后让它们各自前往不同的路径,最终选择最佳路径。
  • 防御性复制:假设你想返回某人Person当时的出生日期。明智的做法是Person先创建一个克隆,然后获取其出生日期,因为有极小的可能性会被其他代码修改。
  • 快照:克隆允许您拥有对象的快照,从而创建一些您以后可以遍历的历史记录。

附言:克隆不同于复制。复制实际上分为两种类型:

  • 浅复制:复制对象的引用。基本上,在复制过程中,你仍然在操作同一个对象实例。
  • 深度复制:当你创建一个对象的全新实例时,副本会独立于原始对象存在。这基本上就是克隆,也是原型模式的前提。

问题

假设你正在开发一个博客平台,人们可以在这里创建和分享文章。有一天,你的产品负责人来找你,告诉你需要实现重复文章的功能。

你说这很简单,然后就开始工作了。

你想出了一个幼稚的解决方案:

class Article {
    public title;
    public body;
    private created_at;

    constructor(title, body, created_at){
        this.title = title;
        this.body = body;
        this.created_at = created_at;
    }

}
Enter fullscreen mode Exit fullscreen mode
class Client {
    Article article;

    constructor(Article article){
        this.article = article;
    }

    public Article duplicate(){
        const clone = new Article();
        clone.title = this.article.title;
        clone.body = this.article.body;

    }

}
Enter fullscreen mode Exit fullscreen mode

你看到问题了吗?

我们创建了一个新Article对象,并将标题和正文从初始对象复制到复制的对象,但是created_at字段怎么办?

我们不能简单地复制它,因为它是一个私有字段。一个解决方案是直接将其公开,但这不是好的做法。

另一个问题是,我们的客户端现在与Article类耦合在一起,如果我们想要复制另一个类的对象,我们将不得不再次创建整个过程,但针对不同的类。

我们可以做得更好。

解决方案

原型模式将克隆委托给实际对象。

但首先让我们为所有可克隆的对象创建一个通用接口。

interface Cloneable {
    public clone()
}
Enter fullscreen mode Exit fullscreen mode

现在已经完成,让我们重构我们的Article类以使用这个接口。

class Article implements Cloneable {
    public title;
    public body;
    private created_at;

    constructor(title, body, created_at){
        this.title = title;
        this.body = body;
        this.created_at = created_at;
    }

    public clone(){
        const clone = new Article(this.title, this.body, this.created_at);

        return clone;
    }

}
Enter fullscreen mode Exit fullscreen mode

我们的Article类现在有一个 clone 方法,它返回当前对象的克隆以供使用。

在我们的Client课堂上,我们可以简单地:

class Client {
    Article article;

    constructor(Article article){
        this.article = article;
    }

    public Article duplicate(){
        return this.article.clone();
    }

}
Enter fullscreen mode Exit fullscreen mode

很简单,这就是原型模式的基本前提。记住,大多数编程语言已经实现了这个功能,所以你不必自己实现,但了解其底层工作原理还是很有好处的。

何时使用这种模式?

  • 当客户端不需要依赖具体类来复制对象时,请使用原型模式。
  • 当您想要限制仅在初始字段值上有所不同的子类的数量时,请使用该模式。

优点

  • 您可以更方便地克隆对象。
  • 您的客户端代码不必依赖于对象的具体类。
  • 您可以摆脱重复的初始化代码,而只需简单地克隆对象即可。
  • 你可以用继承的替代方案,不用创建一堆带有不同配置的类。只需创建一个类,然后每次复制它并应用不同的配置即可。

缺点

  • 克隆复杂对象可能非常棘手并导致混乱的代码。

结论

这是迄今为止我们介绍的最简单的设计模式,但不要忘记:

“知己知彼,百战不殆”

更进一步,看看在您自己的项目中可以使用这种模式的方法。

今天你学到了:

  • 原型模式。
  • 原型模式的实现。
  • 识别可以使用原型模式的机会。
  • 这有优点也有缺点。

感谢阅读!

进一步阅读

如果你想了解更多关于设计模式的知识,我推荐你 读《深入设计模式》。这本书以一种有趣且引人入胜的方式,解释了 GoF 书中提到的所有 23 种设计模式。

我推荐的另一本书是 《Heads First 设计模式:大脑友好指南》,其中的解释有趣且易于阅读。

鏂囩珷鏉ユ簮锛�https://dev.to/tamerlan_dev/design-patterns-prototype-14jg
PREV
面试必知的 12 个 JavaScript 数组方法
NEXT
如何在您的网站/应用上检测 VPN 用户