一、简介
所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。
实现:通过工厂模式,在工厂类中,通过一个Map或者List来缓存已经创建好的享元对象,以达到复用的目的。把实例的共享状态和不共享状态分开。
二、UML类图
三、案例
以下是画图器画圆的场景,圆形只有黑色和红色两种,所以可以共享复用。
package mainimport "fmt"const (BLACK = 0RED = 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] = blackCirclecuf.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 intCircleUnit CircleUnitX intY int
}func NewCircle(id int, circleUnit CircleUnit, x, y int) Circle {circle := Circle{}circle.ID = idcircle.CircleUnit = circleUnitcircle.X = xcircle.Y = yreturn 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单例、缓存、对象池:应用单例模式是为了保证对象全局唯一。应用享元模式是为了实现对象复用,节省内存。缓存是为了提高访问效率,而非复用。池化技术中的“复用”理解为“重复使用”,主要是为了节省时间。