Template 模式与 Strategy 模式有很多相似之处。Template 模式首先会定义一个虚拟基类,描述某个组件的骨架(即通用的部分),同时令骨架中存在的某些步骤处于未定义状态。
之后由虚拟基类的子类来实现上述组件中缺失的未定义部分,这部分之前未定义的方法称为 template methods。
此模式的目的在于,定义一系列属于“同一家族”的类,能够囊括某个组件的所有变体。
Template 和 Strategy 模式的目的是非常相似的,它们之间的区别主要在于结构和实现。
两者都允许我们在共享组件中通用部分的同时,修改组件中变化的部分,以此形成不同的变体。不同的地方在于,Strategy 是在运行时动态实现的,而 Template 则在子类定义的时刻就已经被确定了。
配置管理模板
1 | mkdir template && cd template |
package.json
:1
2
3{
"type": "module"
}
configTemplate.js
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32import {promises as fsPromises} from 'fs'
import objectPath from 'object-path'
export class ConfigTemplate {
async load(file) {
console.log(`Deserializing from ${file}`)
this.data = this._deserialize(
await fsPromises.readFile(file, 'utf-8')
)
}
async save(file) {
console.log(`Serializing to ${file}`)
await fsPromises.writeFile(file, this._serialize(this.data))
}
get(path) {
return objectPath.get(this.data, path)
}
set(path, value) {
return objectPath.set(this.data, path, value)
}
_serialize() {
throw new Error('_serialize() must be implemented')
}
_deserialize() {
throw new Error(`_deserialize() must be implemented`)
}
}
其中 configTemplate
虚拟基类实现了配置管理逻辑中的通用部分,即加载和保存文件、获取和设置属性。同时不对序列化和反序列化部分的逻辑进行定义,从而可以通过再创建不同的 Config 子类(即后面的 jsonConfig
和 iniConfig
)来实现具体的序列化逻辑,进而支持特定的配置文件格式。
jsonConfig.js
:1
2
3
4
5
6
7
8
9
10
11import {ConfigTemplate} from './configTemplate.js'
export class JsonConfig extends ConfigTemplate {
_deserialize(data) {
return JSON.parse(data)
}
_serialize(data) {
return JSON.stringify(data, null, ' ')
}
}
iniConfig.js
:1
2
3
4
5
6
7
8
9
10
11
12import {ConfigTemplate} from './configTemplate.js'
import ini from 'ini'
export class IniConfig extends ConfigTemplate {
_deserialize(data) {
return ini.parse(data)
}
_serialize(data) {
return ini.stringify(data)
}
}
index.js
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import {JsonConfig} from './jsonConfig.js'
import {IniConfig} from './iniConfig.js'
async function main() {
const jsonConfig = new JsonConfig()
await jsonConfig.load('samples/conf.json')
jsonConfig.set('nodejs', 'design patterns')
await jsonConfig.save('samples/conf_mod.json')
const iniConifg = new IniConfig()
await iniConifg.load('samples/conf.ini')
iniConifg.set('nodejs', 'design patterns')
await iniConifg.save('samples/conf_mod.ini')
}
main()