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

使用场景

  1. 文本编辑器中的字符对象:在文本编辑器中,字符对象是很多的,但是其中大部分是重复出现的。使用享元模式可以共享相同的字符对象,减少内存占用。
  2. 游戏中的粒子效果:在游戏开发中,粒子效果是常见的,而且通常会存在大量的粒子对象。使用享元模式可以共享相同的粒子对象,以节省内存和提高性能。
  3. 操作系统中的字体对象:在操作系统中,字体对象可能会被多个应用程序同时使用。使用享元模式可以共享相同的字体对象,减少内存消耗。
  4. Web服务器中的连接池:在Web服务器中,经常需要与客户端建立连接。使用享元模式可以共享连接对象,减少连接的创建和销毁开销。
  5. 图形用户界面中的图标和按钮:在图形用户界面中,图标和按钮是常见的UI元素,而且通常会存在大量的相似对象。使用享元模式可以共享相同的图标和按钮对象,减少内存占用。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package main

import "fmt"

// BulletFlyweight 定义了子弹的共享外观
type BulletFlyweight struct {
shape string
color string
damage int
}

// NewBulletFlyweight 创建新的子弹享元对象
func NewBulletFlyweight(shape, color string, damage int) *BulletFlyweight {
return &BulletFlyweight{
shape: shape,
color: color,
damage: damage,
}
}

// Bullet 是子弹对象,包含外部状态(位置等)和共享的外观
type Bullet struct {
x, y int
flyweight *BulletFlyweight
}

// NewBullet 创建新的子弹对象
func NewBullet(x, y int, flyweight *BulletFlyweight) *Bullet {
return &Bullet{
x: x,
y: y,
flyweight: flyweight,
}
}

// Draw 方法用于绘制子弹,共享外观由 flyweight 提供
func (b *Bullet) Draw() {
fmt.Printf("Drawing %s %s bullet at (%d, %d) causing %d damage\n", b.flyweight.color, b.flyweight.shape, b.x, b.y, b.flyweight.damage)
}

func main() {
// 创建共享的子弹外观
sharedBullet := NewBulletFlyweight("round", "red", 10)

// 创建多个子弹对象,共享相同的外观
bullet1 := NewBullet(0, 0, sharedBullet)
bullet2 := NewBullet(10, 20, sharedBullet)
bullet3 := NewBullet(5, 15, sharedBullet)

// 绘制子弹
bullet1.Draw()
bullet2.Draw()
bullet3.Draw()
}

结语

享元模式适用于需要大量相似对象的场景,通过共享(缓存)对象来减少内存占用和提高性能。通过将对象的内部状态和外部状态分离,享元模式可以实现对象的共享,并且保证对象的外部状态可以在不同的上下文中变化。


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。