【设计模式】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
}
相关推荐
我命由我123458 小时前
CesiumJS 笔记 - 获取容器中心点、Cartesian3 clone 方法、修改 Cartesian3 对象的高度
前端·javascript·css·前端框架·html·html5·js
略略略咯咯8 小时前
(总结)设计模式
设计模式
抱抱宝9 小时前
Agent-study项目教程(03):手写 Mini-ReAct Agent(不依赖框架)
javascript·人工智能·gpt·react.js·prompt·agent
用户938515635079 小时前
Next.js 笔记系统(二):Redis 数据服务与侧边栏组件拆分实战
javascript·全栈
Heo13 小时前
大厂前端调试不能只会debugger
前端·javascript·面试
windliang14 小时前
Claude Code 源码分析(十二):错误处理与自动恢复:让 Agent 稳定运行
前端·javascript·面试
默_笙14 小时前
🛬 前端路由的"高级玩法":懒加载、404、鉴权路由,一个都不能少(下篇)
前端·javascript
sunly_14 小时前
TypeScript:3、类型声明与类型推断
javascript·ubuntu·typescript
奥莱维16 小时前
【无标题】
java·前端·javascript
黄金决明子17 小时前
浏览器Window底层操作全解
前端·javascript