行为型:五. 策略模式
策略模式是什么
策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。
为什么用策略模式
当你想使用对象中各种不同的算法变体,并希望能在运行时切换算法时,可使用策略模式。策略模式让你能将不同行为抽取到一个独立类层次结构中, 并将原始类组合成同一个, 从而减少重复代码。策略模式让你在有多种算法相似的情况下,减少使用 if...else 或 switch...case 所带来的复杂性和臃肿性。
策略模式怎么实现
这里是以构建缓存的形式来举例,当缓存达到最大限制时就要启动缓存淘汰算法。常用的算法有:
- 最少最近使用 (LRU): 移除最近使用最少的一条条目。
- 先进先出 (FIFO): 移除最早创建的条目。
- 最少使用 (LFU): 移除使用频率最低一条条目。
然后我们可以把每个缓存淘汰算法放入独立的类中,以便可以相互替换算法。
cache.go 构建缓存
package strategy
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--
}
eviction_algo.go 淘汰算法
package strategy
import "fmt"
type evictionAlgo interface {
evict(c *cache)
}
type fifo struct {
}
func (l *fifo) evict(c *cache) {
fmt.Println("Evicting by fifo strtegy")
}
type lru struct {
}
func (l *lru) evict(c *cache) {
fmt.Println("Evicting by lru strtegy")
}
type lfu struct {
}
func (l *lfu) evict(c *cache) {
fmt.Println("Evicting by lfu strtegy")
}
example.go 客户端调用
package strategy
func Example() {
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")
}
优点
- 算法多样性,且具备自由切换功能。
- 你可以将算法的实现和使用算法的代码隔离开来。
- 开闭原则。 你无需对上下文进行修改就能够引入新的策略。
缺点
- 策略类数量增多,且客户端必须知晓策略间的不同以便选择合适的策略。