GoLang设计模式15 - 策略模式

策略模式是一种行为型设计模式。通过策略模式,可以在运行时修改一个对象的行为。

接下来仍然是通过例子来了解策略模式。比如说内存缓存,这是我们在开发中经常使用的东西,大家应该都有一定的了解,接下来就用内存缓存来说明下如何使用策略模式。

MapCache
  • LRU(Least Recently Used):清理最近使用的最少的那些缓存数据
  • FIFO(First In First Out):清理最早放入缓存的那些数据
  • LFU(Least Frequently Used):清理使用频率最低的那部分数据
CacheCacheevictionAlgo
evictionAlgoCache
CacheevictionAlgoevictionAlgoevictionAlgoCache

现在捋一下什么时候使用策略模式:

  1. 当一个对象需要提供不同的行为,而又不想在运行时修改对象时
  2. 当想在运行时选择不同的行为而又不想写大量的条件语句时
  3. 当为同一种行为准备了不同的算法时

下面是策略模式的UML类图:

这里是我们当前这个内存缓存案例的UML图:

具体代码如下:

evictionAlgo.go:

type evictionAlgo interface {
	evict(c *cache)
}

lru.go:

import "fmt"

type lru struct {
}

func (l *lru) evict(c *cache) {
	fmt.Println("Evicting by lru strategy")
}

fifo.go:

import "fmt"

type fifo struct {
}

func (l *fifo) evict(c *cache) {
	fmt.Println("Evicting by fifo strategy")
}

lfu.go

import "fmt"

type lfu struct {
}

func (l *lfu) evict(c *cache) {
	fmt.Println("Evicting by lfu strategy")
}

cache.go

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

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")
}

执行后的输出内容为:

Evicting by lfu strategy
Evicting by lru strategy
Evicting by fifo strategy

代码已上传至GitHub: zhyea / go-patterns / strategy-pattern

END!!