5. 原型模式(Prototype)

问题:创建对象成本高(属性多或计算复杂),想基于已有对象克隆。

核心:通过克隆已有实例来创建新对象,而不是从头 new

interface PersonPrototype {
  name: string;
  greet(): string;
  clone(): PersonPrototype;
}

const prototype: PersonPrototype = {
  name: '',
  greet() { return `你好,我是${this.name}`; },
  clone() { return Object.create(this) as PersonPrototype; }
};

const personA = prototype.clone();
personA.name = '小明';

const personB = prototype.clone();
personB.name = '小红';

console.log(personA.greet()); // 你好,我是小明
console.log(personB.greet()); // 你好,我是小红
package prototype

import "fmt"

type Prototype interface {
  Clone() Prototype
  Greet() string
}

type Person struct {
  Name string
  Age  int
}

func (p *Person) Clone() Prototype {
  return &Person{Name: p.Name, Age: p.Age}
}

func (p *Person) Greet() string {
  return fmt.Sprintf("你好,我是%s", p.Name)
}

实战场景

  • 表单默认值复制:新增多条相似配置、规则或商品 SKU 时,先克隆模板对象,再修改少量字段。
  • 游戏对象生成:大量敌人、子弹、道具共享基础属性,通过原型复制后补上坐标、血量、随机属性。
  • 图形编辑器:复制一个图层、节点、流程块或画布元素,本质上是克隆已有对象并生成新的 id。
  • 配置快照:复杂配置对象解析成本高,可以先生成一个标准模板,再按环境克隆并覆盖差异。
  • 富文本节点复制:编辑器中复制段落、表格、图片块时,需要保留结构和样式,同时让新节点拥有独立引用。
  • 测试 fixture:创建复杂测试对象时,先准备一个可靠样板,再在每个用例里克隆并覆盖关键字段。
  • 工作流模板:审批流、自动化规则、项目模板可以被复制成新的实例,再绑定具体用户、部门或时间。
  • 可视化组件模板:仪表盘里复制一个图表卡片,保留查询、样式和布局配置,只改数据源或标题。
  • 离线草稿:把已发布内容克隆成草稿版本,编辑草稿不影响线上版本。
  • 需要注意深浅拷贝:如果对象里有数组、Map、嵌套对象或外部资源引用,要明确哪些需要共享,哪些需要复制。

JavaScript 的原型链本身就是这个思想的体现。Object.create() 是最直接的原型克隆方式。