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

 更新时间:2023年06月28日 08:22:42   作者:demo007x  
享元是一种结构型设计模式,它允许你在消耗少量内存的情况下支持大量对象,模式通过共享多个对象的部分状态来实现上述功能,换句话来说,享元会将不同对象的相同数据进行缓存以节省内存,本文就将通过代码示例给大家详细介绍一下享元模式

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

概念示例

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

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

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

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

  • 10 个玩家对象各自创建不同的服装对象, 并将其嵌入。 总共会创建 10 个服装对象。
  • 我们创建两个服装对象:
  • 单一恐怖分子服装对象: 其将在 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) getDressFactoryByType(dressType string) (Dress, error) {
	if d.dressMap[dressType] != nil {
		return d.dressMap[dressType], nil
	}
	if dressType == TerroristDressType {
		d.dressMap[dressType] = newTerrorisDress()
		return d.dressMap[dressType], nil
	}
	if dressType == CounterTerrroristDressType {
		d.dressMap[dressType] = newCounterTerrroristDress()
		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 newTerrorisDress() *TerroristDress {
	return &TerroristDress{color: "red"}
}

counterTerroristDress.go: 具体享元对象

package main
// 享元接口
type CounterTerrroristDress struct {
	color string
}
func (c *CounterTerrroristDress) getColor() string {
	return c.color
}
func newCounterTerrroristDress() *CounterTerrroristDress {
	return &CounterTerrroristDress{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().getDressFactoryByType(dressType)
	return &Player{
		dress:      dress,
		playerType: playerType,
	}
}
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, 01),
	}
}
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: tDress
DressColor: red
DressColorType: ctDress
DressColor: green

到此这篇关于Go设计模式之享元模式讲解和代码示例的文章就介绍到这了,更多相关Go 享元模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang收支记账程序详细编写过程

    Golang收支记账程序详细编写过程

    这篇文章主要介绍了Golang实现收支记账程序流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • go原子级内存操作实现

    go原子级内存操作实现

    原子级内存操作是在多线程并发执行时,能够确保某个内存操作是不可中断的操作,本文主要介绍了go原子级内存操作实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Go chassis云原生微服务开发框架应用编程实战

    Go chassis云原生微服务开发框架应用编程实战

    这篇文章主要为大家介绍了Go chassis云原生微服务开发框架应用编程实战示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Go语言七篇入门教程四通道及Goroutine

    Go语言七篇入门教程四通道及Goroutine

    这篇文章主要为大家介绍了Go语言的通道及Goroutine示例详解,本文是Go语言七篇入门系列篇,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-11-11
  • GoLang协程库libtask学习笔记

    GoLang协程库libtask学习笔记

    libtask一个C语言的协程库,是go语言的前身很早期的原型. 测试机器是我的mac air 安装的centos虚拟机(只有一个核), 代码没有采用任何优化,只是使用默认配置
    2022-12-12
  • 详解Go语言如何对数据库进行CRUD操作

    详解Go语言如何对数据库进行CRUD操作

    在这篇文章中,主要带大家来学习一下在Go语言中如何对数据库进行CRUD操作,从而探讨一下Go的接口编程,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-05-05
  • go-zero rpc分布式微服务使用详解

    go-zero rpc分布式微服务使用详解

    文章介绍了如何安装Go环境、配置Go环境、安装goctl工具以及创建第一个项目,详细的步骤包括生成项目、配置文件、启动服务、测试项目等,文章还涵盖了Go Zero框架的基本概念,如API定义、服务间通信、业务逻辑实现等
    2026-01-01
  • 在ubuntu下安装go开发环境的全过程

    在ubuntu下安装go开发环境的全过程

    Go语言是谷歌公司开发的编程语言,虽然安装和配置go很简单,但是很多初学者在第一次安装go环境时会遇到各种坑,下面这篇文章主要给大家介绍了关于在ubuntu下安装go开发环境的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • 详解Golang实现请求限流的几种办法

    详解Golang实现请求限流的几种办法

    这篇文章主要介绍了详解Golang实现请求限流的几种办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Golang导入包的几种方式(点,别名与下划线)

    Golang导入包的几种方式(点,别名与下划线)

    这篇文章主要介绍了Golang导入包的几种方式(点,别名与下划线),文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02

最新评论