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

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

向内存里存东西对于GoLang来说算是比较简单的事情,通过Map就可以做到,不过还是建议创建一个Cache struct来稍稍封装一下。不过我们都知道,内存缓存占用的空间是有上限的。当快达到上限时,就需要清理一下缓存中已有的内容。如下是清理缓存的一些常见的算法:

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

现在的问题是如何将Cache和清理算法解耦,这样在运行时就可以调整清理缓存的算法了。但也要注意,在添加新的清理算法时,不应该改动Cache。这时候就需要用到策略模式了。策略模式建议为相同业务的各种算法创建一个算法组,然后将每种算法都封装起来,使之有相同的接口,并且不同算法之间可以互换。清理缓存的算法的接口就可以命名为:evictionAlgo

然后将evictionAlgo接口嵌入Cache中就可以了。

不同于让Cache直接自己继承evictionAlgo接口,现在可以通过evictionAlgo接口来组装不同的清理算法。因为evictionAlgo是一个接口,这样在运行的时候就可以将之赋值为LRU、FIFO或LFU,而不需要对Cache struct做任何调整。

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

  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!!

GoLang设计模式15 - 策略模式的更多相关文章

  1. python设计模式之策略模式

    每次看到项目中存在大量的if else代码时,都会心生一丝不安全感. 特别是产品给的需求需要添加或者更改一种if条件时,生怕会因为自己的疏忽而使代码天崩地裂,哈哈,本文的目的就是来解决这种不安全感的, ...

  2. 设计模式:策略模式(Strategy)

    定   义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...

  3. PHP设计模式之策略模式

    前提: 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查 找.排序等,一种常用的方法是硬编码(Hard Cod ...

  4. JavaScript设计模式之策略模式(学习笔记)

    在网上搜索“为什么MVC不是一种设计模式呢?”其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composite).所以我今天选 ...

  5. c++设计模式15 --组合模式

    今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...

  6. 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)

    原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...

  7. JavaScript设计模式之策略模式

    所谓"条条道路通罗马",在现实中,为达到某种目的往往不是只有一种方法.比如挣钱养家:可以做点小生意,可以打分工,甚至还可以是偷.抢.赌等等各种手段.在程序语言设计中,也会遇到这种类 ...

  8. 【设计模式】【应用】使用模板方法设计模式、策略模式 处理DAO中的增删改查

    原文:使用模板方法设计模式.策略模式 处理DAO中的增删改查 关于模板模式和策略模式参考前面的文章. 分析 在dao中,我们经常要做增删改查操作,如果每个对每个业务对象的操作都写一遍,代码量非常庞大. ...

  9. [design-patterns]设计模式之一策略模式

    设计模式 从今天开始开启设计模式专栏,我会系统的分析和总结每一个设计模式以及应用场景.那么首先,什么是设计模式呢,作为一个软件开发人员,程序人人都会写,但是写出一款逻辑清晰,扩展性强,可维护的程序就不 ...

随机推荐

  1. P4780-Phi的反函数【dfs】

    正题 题目链接:https://www.luogu.com.cn/problem/P4780 题目大意 给出\(n\),求一个最小的\(x\)满足\(\varphi(x)=n\). 若不存在或者大于\ ...

  2. mybatis中#{}与${}取值的区别

    1. 首先对于一个接口 Employee getEmpByIdAndName(@Param("id") Integer id,@Param("empName") ...

  3. Redis分布式锁,看完不懂你打我

    简易的redis分布式锁 加锁: set key my_random_value NX PX 30000 这个命令比setnx好,因为可以同时设置过期时间.不设置过期时间,应用挂了,解不了锁,就一直锁 ...

  4. mysql8 主从搭建

    主:192.168.10.2 从:192.168.10.3 主:1.登录mysql,授权账号,让从数据库可以进行复制. mysql CREATE USER 'repl'@'192.168.10.3' ...

  5. vue-devtools 安装

    vue火了很久了,但是一直赶不上时代步伐的我今天才开始学,首先,根据vue官网介绍,推荐安装Vue Devtools.它允许你在一个更友好的界面中审查和调试 Vue 应用. 首先,将vue-devto ...

  6. 重修 Tarjan

    Tarjan是谁 Tarjan's SCCs(有向图强连通分量)algorithm 给定⼀个有向图 \(G\),若存在 \(rt\in V\),满⾜从 \(rt\) 出发能到达 \(V\) 中的所有的 ...

  7. D:\Software\Keil5\ARM\PACK\Keil\STM32F1xx_DFP\2.1.0\Device\Include\stm32f10x.h(483): error: #5: cannot open source input file "core_cm3.h": No such file or directory

    1. 错误提示信息: D:\Software\Keil5\ARM\PACK\Keil\STM32F1xx_DFP\2.1.0\Device\Include\stm32f10x.h(483): erro ...

  8. 初学python-day9 函数1(已更新)

    函数 一.函数基础 1.什么是函数 在一个完整的项目中,某些功能会被重复使用,那么会将代码段封装成函数,当我们要使用的时候,直接调用即可. 函数是可以实现一定的小程序或者功能. 优点: 增加了代码的重 ...

  9. 《JavaScript DOM编程艺术》:innerHTML

    来源:第七章 动态创建标记 innerHTML: 1.HTML页面建立空白div: <div id="testdiv"> </div> <script ...

  10. 北航OO第三单元总结

    JML基础梳理及工具链 JML的全称是Java Modeling language,即Java建模语言.JML是一种行为接口规格.它为严格的程序设计提供了一套行之有效的方法.通过JML不仅可以基于规格 ...