一、简介
所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。
实现:通过工厂模式,在工厂类中,通过一个Map或者List来缓存已经创建好的享元对象,以达到复用的目的。把实例的共享状态和不共享状态分开。
二、UML类图
三、案例
以下是画图器画圆的场景,圆形只有黑色和红色两种,所以可以共享复用。
package main
import "fmt"
const (
BLACK = 0
RED = 1
)
type CircleUnit struct {
Color int
}
func NewCircleUnit(color int) CircleUnit {
return CircleUnit{Color: color}
}
type CircleUnitFactory struct {
CircleMap map[int]CircleUnit
}
func (cuf *CircleUnitFactory) Init() {
blackCircle := NewCircleUnit(BLACK)
redCircle := NewCircleUnit(RED)
cuf.CircleMap = make(map[int]CircleUnit)
cuf.CircleMap[blackCircle.Color] = blackCircle
cuf.CircleMap[redCircle.Color] = redCircle
}
func (cuf *CircleUnitFactory) GetCircleUnit(color int) (CircleUnit, error) {
cu, ok := cuf.CircleMap[color]
if !ok {
return cu, fmt.Errorf("color[%v] is not exist", color)
}
return cu, nil
}
type Circle struct {
ID int
CircleUnit CircleUnit
X int
Y int
}
func NewCircle(id int, circleUnit CircleUnit, x, y int) Circle {
circle := Circle{}
circle.ID = id
circle.CircleUnit = circleUnit
circle.X = x
circle.Y = y
return circle
}
type DrawingBoard struct {
CircleMap map[int]Circle
}
func (db *DrawingBoard) Init() {
db.CircleMap = make(map[int]Circle)
}
func (db *DrawingBoard) Draw(circle Circle) {
db.CircleMap[circle.ID] = circle
}
func (db *DrawingBoard) Show() {
for k, v := range db.CircleMap {
fmt.Printf("id: %v, color: %v, x: %v, y: %v\n", k, v.CircleUnit.Color, v.X, v.Y)
}
}
func main() {
circleUnitFactory := CircleUnitFactory{}
circleUnitFactory.Init()
drawingBoard := DrawingBoard{}
drawingBoard.Init()
black, _ := circleUnitFactory.GetCircleUnit(BLACK)
red, _ := circleUnitFactory.GetCircleUnit(RED)
drawingBoard.Draw(NewCircle(1, black, 1, 1))
drawingBoard.Draw(NewCircle(2, red, 2, 2))
drawingBoard.Draw(NewCircle(3, black, 3, 3))
drawingBoard.Show()
}
四、对比
享元模式VS单例、缓存、对象池:应用单例模式是为了保证对象全局唯一。应用享元模式是为了实现对象复用,节省内存。缓存是为了提高访问效率,而非复用。池化技术中的“复用”理解为“重复使用”,主要是为了节省时间。