【设计模式】4、prototype 原型模式

四、prototype 原型模式

https://refactoringguru.cn/design-patterns/prototype

如果希望 复制对象, 可使用 "prototype 模式"

如果 "待复制的对象" 是 interface 而不是 class, 或者如果 class 有 private 变量时. 无法知道 "待复制的对象"的细节, 则需要其实现 "clone()" 方法供外部调用.

4.1 inode

本例希望实现文件系统的复制功能. 数据结构是 inode 接口, file 和 folder 都实现了该接口. 详见 https://refactoringguru.cn/design-patterns/prototype/go/example

当然, 另一条路是: 也可以直接用序列化+反序列化实现复杂对象的 clone()

4.1.1 inode_test

go 复制代码
package _41inode

import "testing"

func TestInode(t *testing.T) {
	d1 := &directory{
		name:     "json",
		children: []inode{&file{name: "a.json"}, &file{name: "b.json"}},
	}
	d2 := &directory{
		name:     "yaml",
		children: []inode{&file{"c.yaml"}, &file{"d.yaml"}},
	}
	f1 := &file{name: "e.txt"}
	f2 := &file{name: "f.sql"}

	directoryHome := directory{
		name:     "/home",
		children: []inode{d1, d2, f1, f2},
	}
	directoryHome.print(printIndent)

	cp := directoryHome.clone()
	cp.print("  ")
}

// code result
=== RUN   TestInode
  /home
    json
      a.json
      b.json
    yaml
      c.yaml
      d.yaml
    e.txt
    f.sql
  /home_clone
    json_clone
      a.json_clone
      b.json_clone
    yaml_clone
      c.yaml_clone
      d.yaml_clone
    e.txt_clone
    f.sql_clone
--- PASS: TestInode (0.00s)
PASS

4.1.2 inode

go 复制代码
package _41inode

// inode 是文件系统的节点
type inode interface {
	// 打印此节点的信息, indent 是缩进符(如\t)
	print(indent string)
	// 复制此节点
	clone() inode
}

const printIndent = "  "

4.1.3 file

go 复制代码
package _41inode

import "fmt"

type file struct {
	// 文件名
	name string
}

func (f *file) print(indent string) {
	str := indent + f.name
	fmt.Println(str)
}

func (f *file) clone() inode {
	return &file{name: f.name + "_clone"}
}

4.1.4 directory

go 复制代码
package _41inode

import (
	"fmt"
)

type directory struct {
	// 目录名
	name string
	// 子节点
	children []inode
}

func (d *directory) print(indent string) {
	fmt.Println(indent + d.name)
	for _, child := range d.children {
		child.print(indent + printIndent) // 在基础 indent 的基础上, 再添加 printIndent
	}
}

func (d *directory) clone() inode {
	children := make([]inode, 0)
	for _, child := range d.children {
		children = append(children, child.clone())
	}
	cp := &directory{
		name:     d.name + "_clone",
		children: children,
	}
	return cp
}
相关推荐
爱上妖精的尾巴1 小时前
6-4 WPS JS宏 不重复随机取值应用
开发语言·前端·javascript
三七吃山漆3 小时前
攻防世界——wife_wife
前端·javascript·web安全·网络安全·ctf
用户47949283569153 小时前
面试官问"try-catch影响性能吗",我用数据打脸
前端·javascript·面试
GISer_Jing3 小时前
前端营销技术实战:数据+AI实战指南
前端·javascript·人工智能
嘉琪0014 小时前
Vue3+JS 高级前端面试题
开发语言·前端·javascript
vipbic4 小时前
用 Turborepo 打造 Strapi 插件开发的极速全栈体验
前端·javascript
天涯学馆4 小时前
为什么 JavaScript 可以单线程却能处理异步?
前端·javascript
asdfg12589636 小时前
JS中的闭包应用
开发语言·前端·javascript
kirk_wang6 小时前
Flutter 导航锁踩坑实录:从断言失败到类型转换异常
前端·javascript·flutter
梦里不知身是客116 小时前
spark中如何调节Executor的堆外内存
大数据·javascript·spark