享元模式是一种结构型设计模式, 它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 能在有限的内存容量中载入更多对象
逻辑结构
在享元模式中,有四个角色:
- Flyweight(抽象享元):声明公共方法,这些方法可以向外界提供对象的内部状态。
- ConcreteFlyweight(具体享元):实现抽象享元接口,保存对象内部状态,并且可以被共享。
- FlyweightFactory(享元工厂):维护一个享元池(Flyweight Pool),用于存储已经创建的共享对象。客户端可以向工厂请求一个享元,如果工厂中不存在该享元,则创建新的享元并将其加入到享元池中;否则直接从享元池中返回已有的享元

代码实现
代码路径:https://github.com/XBoom/DesignPatterns/tree/main/13_Component
-
首先,定义公共方法,需要被享元的内容
1
2
3
4// Flyweight 是享元接口
type Flyweight interface {
Operation(extrinsicState string)
} -
然后定义具体的享元操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14// ConcreteFlyweight 是具体享元类
type ConcreteFlyweight struct {
intrinsicState string
}
func NewConcreteFlyweight(intrinsicState string) *ConcreteFlyweight {
return &ConcreteFlyweight{
intrinsicState: intrinsicState,
}
}
func (f *ConcreteFlyweight) Operation(extrinsicState string) {
fmt.Printf("具体享元对象:内部状态为 %s,外部状态为 %s\n", f.intrinsicState, extrinsicState)
} -
第三步就是一个享元工厂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// FlyweightFactory 是享元工厂类
type FlyweightFactory struct {
flyweights map[string]Flyweight
}
func NewFlyweightFactory() *FlyweightFactory {
return &FlyweightFactory{
flyweights: make(map[string]Flyweight),
}
}
func (ff *FlyweightFactory) GetFlyweight(key string) Flyweight {
if flyweight, ok := ff.flyweights[key]; ok {
return flyweight
}
flyweight := NewConcreteFlyweight(key)
ff.flyweights[key] = flyweight
return flyweight
}
执行
1 | factory := NewFlyweightFactory() |
结果
1 | 具体享元对象:内部状态为 A,外部状态为 1 |
总结
- 仅在程序必须支持大量对象且没有足够的内存容量时使用享元模式(类似与内存池,但是这个重复利用的不是分配的内存而是对象)
- 享元中共享的是对象,如果对象多处使用修改对象内容需要注意(类似指针),其次需要考虑并发处理
- 好处就是减少了内存使用,但这种适用的是常驻对象,临时对象需要考虑内存上限与过期删除问题
- 有一个类似的 共享调用 共享的是请求也可以看看