原型模式
代码实现
package prototype
import (
"encoding/json"
"time"
)
// Keyword 搜索关键字
type Keyword struct {
word string
visit int
UpdatedAt *time.Time
}
// Clone 这里使用序列化与反序列化的方式深拷贝
func (k *Keyword) Clone() *Keyword {
var newKeyword Keyword
b, _ := json.Marshal(k)
json.Unmarshal(b, &newKeyword)
return &newKeyword
}
// Keywords 关键字 map
type Keywords map[string]*Keyword
// Clone 复制一个新的 keywords
// updatedWords: 需要更新的关键词列表,由于从数据库中获取数据常常是数组的方式
func (words Keywords) Clone(updatedWords []*Keyword) Keywords {
newKeywords := Keywords{}
for k, v := range words {
// 这里是浅拷贝,直接拷贝了地址
newKeywords[k] = v
}
// 替换掉需要更新的字段,这里用的是深拷贝
for _, word := range updatedWords {
newKeywords[word.word] = word.Clone()
}
return newKeywords
}
测试用例
package prototype
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestKeywords_Clone(t *testing.T) {
updateAt, _ := time.Parse("2006", "2020")
words := Keywords{
"testA": &Keyword{
word: "testA",
visit: 1,
UpdatedAt: &updateAt,
},
"testB": &Keyword{
word: "testB",
visit: 2,
UpdatedAt: &updateAt,
},
"testC": &Keyword{
word: "testC",
visit: 3,
UpdatedAt: &updateAt,
},
}
now := time.Now()
updatedWords := []*Keyword{
{
word: "testB",
visit: 10,
UpdatedAt: &now,
},
}
got := words.Clone(updatedWords)
assert.Equal(t, words["testA"], got["testA"])
assert.NotEqual(t, words["testB"], got["testB"])
assert.NotEqual(t, updatedWords[0], got["testB"])
assert.Equal(t, words["testC"], got["testC"])
}