瞅瞅我的新 Git 课! 嘿!瞅瞅我的新 Git 课! 嘿!GitByBit.com 上有我的新 Git 课,瞅瞅! 嘿!想来点 Git 的爽复习?GitByBit.com 上我的新课,瞅瞅!
享元

Go 享元模式讲解和代码示例

享元是一种结构型设计模式 它允许你在消耗少量内存的情况下支持大量对象

模式通过共享多个对象的部分状态来实现上述功能 换句话来说 享元会将不同对象的相同数据进行缓存以节省内存

概念示例

在游戏 反恐精英 恐怖分子和反恐精英身着不同类型的衣物 为了简便起见 我们就假设双方都各有一种服装类型 服装对象嵌入在玩家对象之中 如下所示

下面是玩家的结构体 我们可以看到 服装对象是嵌入在玩家结构体之中的

type player struct {
dress      dress
playerType string // 可为 T 或 CT
lat        int
long       int
}

假设目前有 5 名恐怖分子和 5 名反恐精英 一共是 10 名玩家 那么关于服装 我们就有两个选项了

  1. 10 个玩家对象各自创建不同的服装对象 并将其嵌入 总共会创建 10 个服装对象

  2. 我们创建两个服装对象

  • 单一恐怖分子服装对象 其将在 5 名恐怖分子之间共享
  • 单一反恐精英服装对象 其将在 5 名反恐精英之间共享

你可以看到 方法 1 中我们总共创建了 10 个服装对象 方法 2 中则只有 2 个服装对象 第二种方法 就是我们所遵循的享元设计模式 我们所创建的 2 个服装对象被称为是享元对象

享元模式会从对象中提取出公共部分并创建享元对象 这些享元对象 服装 随后可在多个对象 玩家 中分享 这极大地减少了服装对象的数量 更棒的是即便你创建了更多玩家 也只需这么两个服装对象就足够了

在享元模式中 我们会将享元对象存储在 map 容器中 每当创建共享享元对象的其他对象时 都会从 map 容器中获取享元对象

下面让我们来看看此类安排的内部状态和外部状态

  • 内部状态的服装可在多个恐怖分子和反恐精英对象间共享

  • 玩家位置和玩家所使用的武器就是外部状态 因为其在每个对象中都是不同的

dressFactory.go: 享元工厂

package main

import "fmt"

const (
	//TerroristDressType terrorist dress type
	TerroristDressType = "tDress"
	//CounterTerrroristDressType terrorist dress type
	CounterTerrroristDressType = "ctDress"
)

var (
	dressFactorySingleInstance = &DressFactory{
		dressMap: make(map[string]Dress),
	}
)

type DressFactory struct {
	dressMap map[string]Dress
}

func (d *DressFactory) getDressByType(dressType string) (Dress, error) {
	if d.dressMap[dressType] != nil {
		return d.dressMap[dressType], nil
	}

	if dressType == TerroristDressType {
		d.dressMap[dressType] = newTerroristDress()
		return d.dressMap[dressType], nil
	}
	if dressType == CounterTerrroristDressType {
		d.dressMap[dressType] = newCounterTerroristDress()
		return d.dressMap[dressType], nil
	}

	return nil, fmt.Errorf("Wrong dress type passed")
}

func getDressFactorySingleInstance() *DressFactory {
	return dressFactorySingleInstance
}

dress.go: 享元接口

package main

type Dress interface {
	getColor() string
}

terroristDress.go: 具体享元对象

package main

type TerroristDress struct {
	color string
}

func (t *TerroristDress) getColor() string {
	return t.color
}

func newTerroristDress() *TerroristDress {
	return &TerroristDress{color: "red"}
}

counterTerroristDress.go: 具体享元对象

package main

type CounterTerroristDress struct {
	color string
}

func (c *CounterTerroristDress) getColor() string {
	return c.color
}

func newCounterTerroristDress() *CounterTerroristDress {
	return &CounterTerroristDress{color: "green"}
}

player.go: 背景

package main

type Player struct {
	dress      Dress
	playerType string
	lat        int
	long       int
}

func newPlayer(playerType, dressType string) *Player {
	dress, _ := getDressFactorySingleInstance().getDressByType(dressType)
	return &Player{
		playerType: playerType,
		dress:      dress,
	}
}

func (p *Player) newLocation(lat, long int) {
	p.lat = lat
	p.long = long
}

game.go: 客户端代码

package main

type game struct {
	terrorists        []*Player
	counterTerrorists []*Player
}

func newGame() *game {
	return &game{
		terrorists:        make([]*Player, 1),
		counterTerrorists: make([]*Player, 1),
	}
}

func (c *game) addTerrorist(dressType string) {
	player := newPlayer("T", dressType)
	c.terrorists = append(c.terrorists, player)
	return
}

func (c *game) addCounterTerrorist(dressType string) {
	player := newPlayer("CT", dressType)
	c.counterTerrorists = append(c.counterTerrorists, player)
	return
}

main.go: 客户端代码

package main

import "fmt"

func main() {
	game := newGame()

	//Add Terrorist
	game.addTerrorist(TerroristDressType)
	game.addTerrorist(TerroristDressType)
	game.addTerrorist(TerroristDressType)
	game.addTerrorist(TerroristDressType)

	//Add CounterTerrorist
	game.addCounterTerrorist(CounterTerrroristDressType)
	game.addCounterTerrorist(CounterTerrroristDressType)
	game.addCounterTerrorist(CounterTerrroristDressType)

	dressFactoryInstance := getDressFactorySingleInstance()

	for dressType, dress := range dressFactoryInstance.dressMap {
		fmt.Printf("DressColorType: %s\nDressColor: %s\n", dressType, dress.getColor())
	}
}

output.txt: 执行结果

DressColorType: ctDress
DressColor: green
DressColorType: tDress
DressColor: red

享元在其他编程语言中的实现

C# 享元模式讲解和代码示例 C++ 享元模式讲解和代码示例 Java 享元模式讲解和代码示例 PHP 享元模式讲解和代码示例 Python 享元模式讲解和代码示例 Ruby 享元模式讲解和代码示例 Rust 享元模式讲解和代码示例 Swift 享元模式讲解和代码示例 TypeScript 享元模式讲解和代码示例