Go设计模式之策略模式讲解和代码示例

 更新时间:2023年08月22日 09:31:34   作者:demo007x  
策略是一种行为设计模式, 它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换,本文就将通过代码示例给大家详细的介绍一下Go的策略模式,需要的朋友可以参考下

Go 策略模式讲解和代码示例

策略是一种行为设计模式, 它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换。

原始对象被称为上下文, 它包含指向策略对象的引用并将执行行为的任务分派给策略对象。 为了改变上下文完成其工作的方式, 其他对象可以使用另一个对象来替换当前链接的策略对象。

概念示例

思考一下构建内存缓存的情形。 由于处在内存中, 故其大小会存在限制。 在达到其上限后, 一些条目就必须被移除以留出空间。 此类操作可通过多种算法进行实现。 一些流行的算法有:

  • 最少最近使用 (LRU): 移除最近使用最少的一条条目。
  • 先进先出 (FIFO): 移除最早创建的条目。
  • 最少使用 (LFU): 移除使用频率最低一条条目。

问题在于如何将我们的缓存类与这些算法解耦, 以便在运行时更改算法。 此外, 在添加新算法时, 缓存类不应改变。

这就是策略模式发挥作用的场景。 可创建一系列的算法, 每个算法都有自己的类。 这些类中的每一个都遵循相同的接口, 这使得系列算法之间可以互换。 假设通用接口名称为 eviction­Algo移除算法 。

现在, 我们的主要缓存类将嵌入至 eviction­Algo接口中。 缓存类会将全部类型的移除算法委派给 eviction­Algo接口, 而不是自行实现。 鉴于 eviction­Algo是一个接口, 我们可在运行时将算法更改为 LRU、 FIFO 或者 LFU, 而不需要对缓存类做出任何更改。

evictionAlgo.go: 策略接口

package main
// 策略接口
type EvictionAlgo interface {
	evict(c *Cache)
}

fifo.go:具体策略

package main
import "fmt"
type Fifo struct{}
func (l *Fifo) evict(c *Cache) {
	fmt.Println("Evicting by fifo strtegy")
}

lru.go:具体策略

package main
import "fmt"
type Lru struct{}
func (l *Lru) evict(c *Cache) {
	fmt.Println("Evicting by lru strtegy")
}

lfu.go:具体策略

package main
import "fmt"
type Lfu struct{}
func (l *Lfu) evict(c *Cache) {
	fmt.Println("Evicting by lfu strtegy")
}

cache.go:背景

package main
type Cache struct {
	storage      map[string]string
	evictionAlgo EvictionAlgo
	capacity     int
	macCapacity  int
}
// 初始化的时候将策略注入到 cache 中
func initCache(e EvictionAlgo) *Cache {
	storage := make(map[string]string)
	return &Cache{
		storage:      storage,
		evictionAlgo: e,
		capacity:     0,
		macCapacity:  2,
	}
}
// 动态修改策略
func (c *Cache) setEvictionAlgo(e EvictionAlgo) {
	c.evictionAlgo = e
}
func (c *Cache) add(key, value string) {
	// 如果缓存中的容量等于了最大容量,则需要执行策略来移除 s
	if c.capacity == c.macCapacity {
		c.evict()
	}
	c.capacity++
	c.storage[key] = value
}
func (c *Cache) evict() {
	c.evictionAlgo.evict(c)
	c.capacity--
}
func (c *Cache) get(key string) {
	delete(c.storage, key)
}

main.go:客户端代码

package main
func main() {
	lfu := &Lfu{}
	cache := initCache(lfu)
	cache.add("a", "1")
	cache.add("b", "2")
	cache.add("c", "3")
	lru := &Lru{}
	cache.setEvictionAlgo(lru)
	cache.add("d", "4")
	fifo := &Fifo{}
	cache.setEvictionAlgo(fifo)
	cache.add("e", "5")
}

output.txt:执行结果

Evicting by lfu strtegy
Evicting by lru strtegy
Evicting by fifo strtegy

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

相关文章

  • Golang中http包的具体使用

    Golang中http包的具体使用

    Go语言内置的net/http包十分优秀,提供了http客户端和服务器的实现,本文主要介绍了Golang中http包的具体使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-05-05
  • Golang中panic与recover的区别

    Golang中panic与recover的区别

    这篇文章主要介绍了Golang中panic与recover的区别,文章基于Golang的基础内容展开panic与recover的区别介绍,需要的小伙伴可以参考一下
    2022-06-06
  • 深入理解Go中的项目代码布局

    深入理解Go中的项目代码布局

    Go 语言的创世项目其实就是 Go 语言项目自身,是全世界第一个 Go 语言项目,本文主要来和大家详细介绍一下Go中的项目代码布局,需要的可以了解下
    2023-11-11
  • golang中sync.Map并发创建、读取问题实战记录

    golang中sync.Map并发创建、读取问题实战记录

    这篇文章主要给大家介绍了关于golang中sync.Map并发创建、读取问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • Golang动态数组的实现示例

    Golang动态数组的实现示例

    动态数组能自动调整大小,与静态数组不同,其大小不固定,可根据需求变化,实现通常依赖于数据结构如链表或数组加额外信息,本文就来介绍一下Golang动态数组的实现示例,感兴趣的可以了解一下
    2024-10-10
  • golang调用c实现的dll接口细节分享

    golang调用c实现的dll接口细节分享

    这篇文章主要介绍了golang调用c实现的dll接口细节分享,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • 8种超简单的Golang生成随机字符串方式分享

    8种超简单的Golang生成随机字符串方式分享

    这篇文章主要为大家详细介绍了8种超简单的Golang生成随机字符串方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • golang中两个协程交替打印数字和字母的实现

    golang中两个协程交替打印数字和字母的实现

    这篇文章给大家介绍了golang中两个协程交替打印数字和字母的实现,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-01-01
  • go grpc安装使用教程

    go grpc安装使用教程

    gRPC是由Google主导开发的RPC框架,使用HTTP/2协议并用ProtoBuf作为序列化工具。这篇文章主要介绍了go grpc安装使用教程,需要的朋友可以参考下
    2018-02-02
  • golang 字符串拼接方法对比分析

    golang 字符串拼接方法对比分析

    这篇文章主要为大家介绍了golang 字符串拼接方法对比分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09

最新评论