设计模式笔记 - 享元模式

173 阅读2分钟

享元模式是一种结构型设计模式,它摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让你能在有限的内存容量中载入更多对象。


解决什么问题?

如果一个类有部分成员可变性低,可在多个对象之间可共享状态的。将这部分抽离出来作为一个单独的类,被其他类复用(通过引用的方式),能大大节省内存消耗。此时可以考虑使用享元模式


实现步骤:

  • 抽离不变部分,形成不变类
  • 定义不变类工厂类
  • 可变类通过不变类的工厂类获取不变类的引用

优势:

  • 如果程序中有很多相似对象,那么你将可以节省大量内存。

劣势:

  • 你可能需要牺牲执行速度来换取内存, 因为他人每次调用享元方法时都需要重新计算部分情景数据。
  • 代码会变得更加复杂。 团队中的新成员总是会问: “为什么要像这样拆分一个实体的状态?”。

下面是实例代码:

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

参考