享元模式是一种结构型设计模式,它摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让你能在有限的内存容量中载入更多对象。
解决什么问题?
如果一个类有部分成员可变性低,可在多个对象之间可共享状态的。将这部分抽离出来作为一个单独的类,被其他类复用(通过引用的方式),能大大节省内存消耗。此时可以考虑使用享元模式。
实现步骤:
- 抽离不变部分,形成
不变类 - 定义
不变类的工厂类 可变类通过不变类的工厂类获取不变类的引用
优势:
- 如果程序中有很多相似对象,那么你将可以节省大量内存。
劣势:
- 你可能需要牺牲执行速度来换取内存, 因为他人每次调用享元方法时都需要重新计算部分情景数据。
- 代码会变得更加复杂。 团队中的新成员总是会问: “为什么要像这样拆分一个实体的状态?”。
下面是实例代码:
package main
import "fmt"
type treeType struct {
color string
texture string
}
type treeFactory struct {
treeTypes []*treeType
}
var treeFac = treeFactory{}
func (t *treeFactory) getTreeType(color string, texture string) *treeType {
for _, v := range t.treeTypes {
if v.color == color && v.texture == texture {
return v
}
}
tt := treeType{
color: color,
texture: texture,
}
t.treeTypes = append(t.treeTypes, &tt)
return &tt
}
type tree struct {
heigh int
width int
t *treeType
}
func (t *tree) draw() {
fmt.Printf("heigh: %d, width: %d, color: %s, texture: %s\n",
t.heigh, t.width, t.t.color, t.t.texture)
}
type forest struct {
trees []*tree
}
func (f *forest) plant(heigh int, width int, color string, texture string) {
tt := treeFac.getTreeType(color, texture)
f.trees = append(f.trees, &tree{
heigh: heigh,
width: width,
t: tt,
})
}
func (f *forest) draw() {
for _, t := range f.trees {
t.draw()
}
}
func main() {
f := forest{}
f.plant(1, 1, "red", "wood")
f.plant(1, 1, "red", "stone")
f.plant(1, 2, "red", "wood")
f.plant(1, 2, "red", "stone")
f.draw()
}
输出:
heigh: 1, width: 1, color: red, texture: wood
heigh: 1, width: 1, color: red, texture: stone
heigh: 1, width: 2, color: red, texture: wood
heigh: 1, width: 2, color: red, texture: stone