【Go-设计模式】原型模式 详解

shadowLogo

原型模式:

概念:

原型实例 指定 创建对象的 种类,并且通过 拷贝这些原型,创建新的对象
原型模式是一种 创建型设计模式,允许 一个对象再创建另外一个可定制的对象,无需知道 如何创建的细节

工作原理是:通过将一个 原型对象 传给那个要发动创建的对象,这个 要发动创建的对象 通过 请求原型对象拷贝它们自己 来实施创建

原型模式配合 原型管理器 使用,使得客户端在 不知道具体类 的情况下,
通过接口管理器得到 新的实例,并且包含 部分预设定配置
doly


UML:

prototype

  • Prototype
    原型管理器,管理 原型对象生成注册
  • ConcretePrototype
    具体的原型类, 实现一个 克隆自己 的操作
  • Client
    让一个 原型对象 克隆自己,从而 创建一个新的对象(属性一样)

示例:

Cloneable接口 · 手动实现

type Cloneable interface {、
	Clone() Cloneable
}

原型管理器

type PrototypeManager struct {
	prototypes map[string]Cloneable
}

func NewPrototypeManager() *PrototypeManager {
	return &PrototypeManager{
		prototypes: make(map[string]Cloneable),
	}
}

func (this PrototypeManager) Get(name string) Cloneable {
	return this.prototypes[name]
}

func (this *PrototypeManager) Set(name string, obj Cloneable) {
	this.prototypes[name] = obj
}

被克隆的类型

type TestModel1 struct {
	Attribute1 int64
}

type TestModel2 struct {
	Attribute2 string
	Attribute3 TestModel1
}

func (this TestModel2) Clone() base23.Cloneable {
	newModel := this
	return newModel
}

测试

package main

import (
	"DemoProject/design/base23" // 根据自己的项目路径定制
	"fmt"
)

var manager base23.PrototypeManager
var model TestModel2

func init() {
	manager := base23.NewPrototypeManager()
	model := TestModel2{
		Attribute2: "youzg",
		Attribute3: TestModel1{
			Attribute1: 666,
		},
	}
	manager.Set("TestModel2", model)
	model.Attribute2 = "YOUZG" // 改变 原对象 的值
}

func main() {
	// clone
	cloneModel1 := manager.Get("TestModel2")
	// model: {YOUZG {666}}, cloneModel1: {youzg {666}}, model is cloneModel1 : [false]
	fmt.Printf("model: %v, cloneModel1: %v, model is cloneModel1 : [%v]\n", model, cloneModel1, model == cloneModel1)

	fmt.Println("===============================================================================")

	cloneModel2 := manager.Get("TestModel2").Clone()
	// model: {YOUZG {666}}, cloneModel2: {youzg {666}}, model is cloneModel2 : [false]
	fmt.Printf("model: %v, cloneModel2: %v, model is cloneModel2 : [%v]\n", model, cloneModel2, model == cloneModel2)


	fmt.Println("===============================================================================")
	cloneModel11 := cloneModel1.(TestModel2)
	cloneModel11.Attribute3.Attribute1 = 999
	// cloneModel11: {youzg {999}}, cloneModel2: {youzg {666}}, cloneModel11 is cloneModel2 : [false]
	fmt.Printf("cloneModel11: %v, cloneModel2: %v, cloneModel11 is cloneModel2 : [%v]\n", cloneModel11, cloneModel2, cloneModel11 == cloneModel2)

	// manager.Get == model.Clone(): false
	fmt.Printf("manager == model.Clone(): %v", cloneModel1 == model.Clone())
}

注意事项

  1. 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率
  2. 不用重新初始化对象,而是 动态地获得对象运行时的状态
  3. 如果 原始对象 发生变化(增加或者减少属性),其它克隆对象 的也会发生相应的变化,无需修改代码
    (注意:此处的更改,是指 对象的结构 发生变化,并不是指 对象的属性值 发生变化,
    被克隆的对象 和 原对象之间,属性值做修改不会影响对方)
  4. 在实现 深克隆 的时候可能需要比较复杂的代码
posted @ 2021-12-12 21:56  在下右转,有何贵干  阅读(119)  评论(0)    收藏  举报