设计模式:原型
原型?
你可能会想到这一点:
或者甚至是这样的:
我很想写一篇关于 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;
}
}
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;
}
}
你看到问题了吗?
我们创建了一个新Article
对象,并将标题和正文从初始对象复制到复制的对象,但是created_at
字段怎么办?
我们不能简单地复制它,因为它是一个私有字段。一个解决方案是直接将其公开,但这不是好的做法。
另一个问题是,我们的客户端现在与Article
类耦合在一起,如果我们想要复制另一个类的对象,我们将不得不再次创建整个过程,但针对不同的类。
我们可以做得更好。
解决方案
原型模式将克隆委托给实际对象。
但首先让我们为所有可克隆的对象创建一个通用接口。
interface Cloneable {
public clone()
}
现在已经完成,让我们重构我们的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;
}
}
我们的Article
类现在有一个 clone 方法,它返回当前对象的克隆以供使用。
在我们的Client
课堂上,我们可以简单地:
class Client {
Article article;
constructor(Article article){
this.article = article;
}
public Article duplicate(){
return this.article.clone();
}
}
很简单,这就是原型模式的基本前提。记住,大多数编程语言已经实现了这个功能,所以你不必自己实现,但了解其底层工作原理还是很有好处的。
何时使用这种模式?
- 当客户端不需要依赖具体类来复制对象时,请使用原型模式。
- 当您想要限制仅在初始字段值上有所不同的子类的数量时,请使用该模式。
优点
- 您可以更方便地克隆对象。
- 您的客户端代码不必依赖于对象的具体类。
- 您可以摆脱重复的初始化代码,而只需简单地克隆对象即可。
- 你可以用继承的替代方案,不用创建一堆带有不同配置的类。只需创建一个类,然后每次复制它并应用不同的配置即可。
缺点
- 克隆复杂对象可能非常棘手并导致混乱的代码。
结论
这是迄今为止我们介绍的最简单的设计模式,但不要忘记:
“知己知彼,百战不殆”
更进一步,看看在您自己的项目中可以使用这种模式的方法。
今天你学到了:
- 原型模式。
- 原型模式的实现。
- 识别可以使用原型模式的机会。
- 这有优点也有缺点。
感谢阅读!
进一步阅读
如果你想了解更多关于设计模式的知识,我推荐你 读《深入设计模式》。这本书以一种有趣且引人入胜的方式,解释了 GoF 书中提到的所有 23 种设计模式。
我推荐的另一本书是 《Heads First 设计模式:大脑友好指南》,其中的解释有趣且易于阅读。
鏂囩珷鏉ユ簮锛�https://dev.to/tamerlan_dev/design-patterns-prototype-14jg