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

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

向内存里存东西对于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. windows kubectl 远程操作k8s

    在windows 电脑上配置kubectl远程操作kubernetes 一.下载windows版的kubectl可执行文件 下载地址 二.创建.kube 建议使用git bash cd ~ mkdir ...

  2. 牛客练习赛89E-牛牛小数点【数论】

    正题 题目链接:https://ac.nowcoder.com/acm/contest/11179/E 题目大意 定义\(f(x)\)表示\(\frac{1}{x}\)的混循环节长度(如果没有循环节就 ...

  3. YbtOJ#853-平面标记【整体二分,凸壳】

    正题 题目链接:http://www.ybtoj.com.cn/contest/119/problem/3 题目大意 给出\(n\)个点\((x_i,y_i)\),\(m\)次给出\((k_i,a_i ...

  4. 今天我抓了个 HTTPS 的包

    之前写过一篇讲 HTTPS 的思想的文章. 破玩意 | 用 HTTPS 传纸条 后来又写了篇用更凝练的语言总体描述了 HTTPS 的主干. 叮咚 | HTTPS 的分支和主干 想必通过这两篇文章,HT ...

  5. keepalived-master-slave

    Master配置 global_defs { notification_email { root@localhost } notification_email_from keeplived@local ...

  6. IIS部署WCF详细教程

    前言: 前段时间接手了公司一个十几年前的老项目,该项目对外提供的服务使用的是WCF进行通信的.因为需要其他项目需要频繁的使用该WCF服务,所以我决定把这个WCF部署到IIS中避免每次调试运行查看效果. ...

  7. nvidia jetson xavier 风扇开机自启动

    作者声明 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 原文链接:https://www.cnblogs.com/phoenixash/p/15 ...

  8. C++核心编程 4 类和对象-封装

    C++面向对象的三大特性:封装.继承.多态 C++认为万事万物皆为对象,对象上有其属性和行为 封装 意义:1.将属性和行为作为一个整体,表现生活中的事物 语法: class 类名{   访问权限:属性 ...

  9. CAD图DWG解析WebGIS可视化技术分析总结

    背景 AutoCAD是国际上著名的二维和三维CAD设计软件,用于二维绘图.详细绘制.设计文档和基本三维设计.现已经成为国际上广为流行的绘图工具..dwg文件格式成为二维绘图的事实标准格式. 但由于Au ...

  10. csh

    在*unix系统中,常用的shell有sh,bash,csh/tcsh, ksh.  sh来自于systemV的Unix,是传统的Unix的shell,直到现在很多的系统管理员仍然喜欢使用sh. ba ...