Prototype Pattern(原型模式)
Clone()
注意原型模式返回的一定是新的内存实例
当直接创建对象的代价比较大时,使用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
五大要素
来看看原型模式的五大要素:
Clone()Clone()
Go实现原型模式
场景
Clone()
prototype.go
package prototype
// Cloneable接口,动物必须实现这个接口
type Cloneable interface {
Clone() Cloneable
}
// 克隆实验室
type CloneLab struct {
animals map[string]Cloneable
}
func NewPrototypeManager() *CloneLab {
return &CloneLab{animals:make(map[string]Cloneable)}
}
// 获取克隆
func (p *CloneLab) Get(name string) Cloneable {
return p.animals[name]
}
// set动物当前属性
func (p *CloneLab) Set(name string,prototype Cloneable) {
p.animals[name] = prototype
}
prototype_test.go
package prototype
import (
"testing"
)
var lab *Cloneable
// 羊
type Sheep struct {
name string
weight int
}
func (s *Sheep) Clone() Cloneable {
tc := *s
return &tc
}
// 牛
type Cow struct {
name string
gender bool
}
func (c *Cow) Clone() Cloneable {
newCow := &Cow{
name: c.name,
gender: c.gender,
}
return newCow
}
func TestClone(t *testing.T) {
sheep1 := &Sheep{
name: "sheep",
weight: 10,
}
sheep2 := sheep1.Clone()
// 这里地址肯定不同,因为是一个新的实例
if sheep1 == sheep2 {
t.Fail()
}
}
func TestCloneFromManager(t *testing.T) {
lab := NewCloneLab()
lab.Set("cow", &Cow{name: "i am cow", gender: true})
c := lab.Get("cow").Clone()
cw := c.(*Cow)
if cw.name != "i am cow" {
t.Fatal("error")
}
}
原型模式与工厂模式的区别
如果我们想要一个空的干净的对象,那么我们可以用工厂模式,但是当我们想获取当前动态的对象的一个拷贝实例,需要用原型模式。