[go] 策略模式

简介: [go] 策略模式

策略模式


定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换。


模型说明


https://pic8.58cdn.com.cn/nowater/webim/big/n_v20eecba43befa4edfa1e4d3b702e7f737.png


  • 上下文(Context)维护指向具体策略的引用,且仅通过策略接口与该对象进行交流。
  • 策略(Strategy)接口是所有具体策略的通用接口,它声明了一个上下文用于执行策略的方法。
  • 具体策略(Concrete Strategies)实现了上下文所用算法的各种不同变体。
  • 当上下文需要运行算法时,它会在其已连接的策略对象上调用执行方法。上下文不清楚其所涉及的策略类型与算法的执行方式。
  • 客户端(Client)会创建一个特定策略对象并将其传递给上下文。上下文则会提供一个设置器以便客户端在运行时替换相关联的策略。


优缺点


1.优点


  • 你可以在运行时切换对象内的算法。
  • 你可以将算法的实现和使用算法的代码隔离开来。
  • 你可以使用组合来代替继承。
  • 开闭原则: 你无需对上下文进行修改就能够引入新的策略。


2.缺点


  • 如果你的算法极少发生改变, 那么没有任何理由引入新的类和接口。 使用该模式只会让程序过于复杂。
  • 客户端必须知晓策略间的不同——它需要选择合适的策略。
  • 许多现代编程语言支持函数类型功能, 允许你在一组匿名函数中实现不同版本的算法。 这样, 你使用这些函数的方式就和使用策略对象时完全相同, 无需借助额外的类和接口来保持代码简洁。


使用场景


  • 当你想使用对象中各种不同的算法变体,并希望能在运行时切换算法时,可使用策略模式。
  • 当你有许多仅在执行某些行为时略有不同的相似类时,可使用策略模式。
  • 如果算法在上下文的逻辑中不是特别重要,使用该模式能将类的业务逻辑与其算法实现细节隔离开来。
  • 当类中使用了复杂条件运算符以在同一算法的不同变体中切换时,可使用该模式。


参考代码


构建内存缓存的情形。


  • 最少最近使用 (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: context
package main
type Cache struct {
    storage      map[string]string
    evictionAlgo EvictionAlgo
    capacity     int
    maxCapacity  int
}
func initCache(e EvictionAlgo) *Cache {
    storage := make(map[string]string)
    return &Cache{
        storage:      storage,
        evictionAlgo: e,
        capacity:     0,
        maxCapacity:  2,
    }
}
func (c *Cache) setEvictionAlgo(e EvictionAlgo) {
    c.evictionAlgo = e
}
func (c *Cache) add(key, value string) {
    if c.capacity == c.maxCapacity {
        c.evict()
    }
    c.capacity++
    c.storage[key] = value
}
func (c *Cache) get(key string) {
    delete(c.storage, key)
}
func (c *Cache) evict() {
    c.evictionAlgo.evict(c)
    c.capacity--
}
// 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:


Evicting by lfu strtegy
Evicting by lru strtegy
Evicting by fifo strtegy
相关文章
|
3月前
|
设计模式 算法 测试技术
动态支付策略:Go 语言中策略模式的妙用
动态支付策略:Go 语言中策略模式的妙用
|
6月前
|
设计模式 算法 Go
[设计模式 Go实现] 行为型~策略模式
[设计模式 Go实现] 行为型~策略模式
|
设计模式 算法 测试技术
Go的策略模式
策略模式是一种行为设计模式,它允许在运行时选择算法的行为。它将算法封装成独立的类,并使它们之间可以互相替换,从而使得算法可以独立于客户端而变化。
75 0
|
设计模式 算法 Go
Go语言实现设计模式之策略模式
策略模式是一种常用的设计模式,它允许在运行时选择算法的行为。本文将详细介绍策略模式的概念和原理,并使用Go语言实现一个示例,以帮助读者更好地理解该设计模式的应用。文章将结合开发和生活中的示例,说明策略模式的应用场景。
212 0
|
设计模式 存储 算法
Go设计模式(20)-策略模式
策略模式可能是很多同学学习到的第一种模式。这个模式确实适合作为开篇模式来讲,主要原因在于该模式简单、纯粹、没有太多技巧,但是很好的表达出了设计模式的理念,让读者能够直观的感受到设计模式带来的好处。
|
设计模式 算法 Go
Go 设计模式-策略模式
Go 设计模式-策略模式
206 0
Go 设计模式-策略模式
|
6天前
|
存储 JSON 监控
Viper,一个Go语言配置管理神器!
Viper 是一个功能强大的 Go 语言配置管理库,支持从多种来源读取配置,包括文件、环境变量、远程配置中心等。本文详细介绍了 Viper 的核心特性和使用方法,包括从本地 YAML 文件和 Consul 远程配置中心读取配置的示例。Viper 的多来源配置、动态配置和轻松集成特性使其成为管理复杂应用配置的理想选择。
23 2
|
4天前
|
Go 索引
go语言中的循环语句
【11月更文挑战第4天】
13 2
|
4天前
|
Go C++
go语言中的条件语句
【11月更文挑战第4天】
16 2
|
9天前
|
Ubuntu 编译器 Linux
go语言中SQLite3驱动安装
【11月更文挑战第2天】
31 7