今天来介绍 Creational Patterns 当中的最後一个模式。
假设这里有一个 Engineer
类别,他除了有个 name
属性之外,还拥有 toolBox
,可以不断加入新的工具,成为超级工具人。Engineer
和 ToolBox
的细节如下:
class Engineer {
name: string
toolBox: ToolBox
constructor(name: string) {
this.name = name
this.toolBox = new ToolBox()
}
}
class ToolBox {
tools: string[]
constructor(){
this.tools = []
}
addTools(tools: string[]) {
this.tools.push(...tools)
}
}
接着,我们就可以产生出一个 Engineer
实例如下
const a = new Engineer('foo')
a.toolBox.addTools(['a', 'b', 'c', 'd', 'e'])
a.name // 'foo'
a.toolBox.tools // ['a', 'b', 'c', 'd', 'e']
但这时候,如果有另外一位使用者,也想要拥有一个跟 a 一样的Engineer
,有一样的名字,和一样的 tools,於是就用同样的方式:先建立Engineer
实例,然後再加入 tools
const b = new Engineer('foo')
b.toolBox.addTools(['a', 'b', 'c', 'd', 'e'])
b.name // 'foo'
b.toolBox.tools // ['a', 'b', 'c', 'd', 'e']
就大功告成了!
今天要建立一个 b 看起来很简单,但如果 a 本身是一个很复杂的物件,或者当中属性的资料需要经过复杂的操作或运算才能获得,那麽要建立一个跟 a 一模一样的 b,就会变得非常麻烦。
那麽,有没有一个可以让我们直接复制 a 的方式呢?
为了让我们可以快速地复制 Engineer
的实例,我们在 Engineer
当中加入了 clone
的方法。另一方面,也需要为 ToolBox
制作 clone
方法。细节如下:
class Engineer {
name: string
toolBox: ToolBox
constructor(name: string) {
this.name = name
this.toolBox = new ToolBox()
}
clone(): this {
const clone = Object.create(this)
clone.toolBox = this.toolBox.clone()
return clone
}
}
class ToolBox {
tools: string[]
constructor(){
this.tools = []
}
addTools(tools: string[]) {
this.tools.push(...tools)
}
clone(): ToolBox {
const clone = new ToolBox()
clone.addTools(this.tools)
return clone
}
}
接着,再让我们重新建立一次 a
const a = new Engineer('foo')
a.toolBox.addTools(['a', 'b', 'c', 'd', 'e'])
然後,我们用 clone
方法来复制 a,立即得到一个跟 a 一模一样的 b
const b = a.clone()
b.name // 'foo'
b.toolBox.tools // ['a', 'b', 'c', 'd', 'e']
虽然复制出来的时候是一模一样,但实际上是两个不同的、独立的个体,所以我们可以分别为他们加入新的 tool,得到不同的结果
a.toolBox.addTools(['f'])
b.toolBox.addTools(['g'])
a.toolBox.tools // ['a', 'b', 'c', 'd', 'e', 'f']
b.toolBox.tools // ['a', 'b', 'c', 'd', 'e', 'g']
透过原型模式,让我们能够快速复制出同样的物件,好处是我们透过复制,我们不需要再次经历过该物件被建立的过程。
不过复制本身也带有一些挑战,如果一个物件里面引用/指向了许多其他的物件,那麽我们就不能单纯这些物件的复制 "reference" (shallow copy),而是要建立出独立物件们 (deep copy)。所以越复杂的物件,要复制它就可能有更多的挑战!
<<: [NestJS 带你飞!] DAY21 - HTTP Module
>>: Day22 [实作] 一对一视讯通话(2): Signaling server
前言 本文说明如何查询即时报价-Snapshots作业。 程序实作 Snapshots(快照):某个...
GitHub 目前提供的 Project 功能为 Board (看板),在撰写这篇文章时,GitH...
routing 在介绍完model验证之後要开始介绍网页程序设计的另一个观念路由routing,更明...
图片来源 继续上一篇的目标设定, 有时候我觉得是因为你心中已有一个"既定的目标"...
还记得在 Day 15 马克杯 装水 Guard 的例子吗? 另外一组例子,一个水瓶或是马克杯的状态...