在Golang项目里,当系统需要生成成千上万个属性大部分相同的对象时,直接new出来会消耗大量内存。享元模式把对象拆成可共享的内部状态和随场景变化的外部状态,用工厂缓存已有实例,达到复用资源对象的目的。

什么是享元模式
享元模式属于结构型设计模式,核心思想是共享。它要求把对象信息分为两部分:
- 内部状态:不随环境改变,可共享,例如字体名称、颜色。
- 外部状态:依赖使用场景,由调用方传入,例如文字内容、坐标。
通过只保存一份内部状态对象,多个调用方搭配不同外部状态来使用,从而减少对象数量。
Golang实现思路
我们以一个文字样式为例,相同字体和大小的样式作为享元,具体绘制的文字和位置作为外部状态。
定义享元接口与结构体
package main
import "fmt"
// Glyph 享元接口
type Glyph interface {
Render(text string, x, y int)
}
// concreteGlyph 具体享元,包含内部状态
type concreteGlyph struct {
font string
size int
}
func (c *concreteGlyph) Render(text string, x, y int) {
fmt.Printf("用字体 %s 大小 %d 绘制文字 %s 位置(%d,%d)n", c.font, c.size, text, x, y)
}
实现享元工厂
工厂负责根据内部状态返回已存在的实例,没有才创建,这就是复用资源对象的关键。
// GlyphFactory 享元工厂
type GlyphFactory struct {
pool map[string]Glyph
}
func NewGlyphFactory() *GlyphFactory {
return &GlyphFactory{pool: make(map[string]Glyph)}
}
func (f *GlyphFactory) GetGlyph(font string, size int) Glyph {
key := fmt.Sprintf("%s_%d", font, size)
if g, ok := f.pool[key]; ok {
return g
}
g := &concreteGlyph{font: font, size: size}
f.pool[key] = g
return g
}
客户端使用
调用方从工厂获取样式对象,并传入外部状态完成绘制,多个文字可共用同一个Glyph。
func main() {
factory := NewGlyphFactory()
g1 := factory.GetGlyph("宋体", 12)
g1.Render("你好", 10, 20)
g2 := factory.GetGlyph("宋体", 12)
g2.Render("世界", 30, 40)
// g1 和 g2 实际指向同一个享元对象
fmt.Println(g1 == g2)
}
适用场景与注意点
享元模式适合对象数量大、内部状态可提取的场景,如文本编辑器、游戏粒子系统。要注意线程安全,如果在并发环境使用工厂,需加sync.Mutex保护map。另外,过度拆分状态会增加代码复杂度,应权衡收益。
合理运用Flyweight Pattern,可以让Golang程序在处理海量细粒度对象时保持较低的内存开销。
GolangFlyweight_Pattern资源对象复用修改时间:2026-07-29 22:39:18