当前位置: 首页 > news >正文

[go] 策略模式

策略模式

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

模型说明

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

优缺点

1.优点

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

2.缺点

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

使用场景

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

参考代码

构建内存缓存的情形。

  • 最少最近使用 (LRU): 移除最近使用最少的一条条目。
  • 先进先出 (FIFO): 移除最早创建的条目。
  • 最少使用 (LFU): 移除使用频率最低一条条目。
// evictionAlgo.go: 策略接口
package maintype EvictionAlgo interface {evict(c *Cache)
}
// fifo.go: 具体策略
package mainimport "fmt"type Fifo struct {
}func (l *Fifo) evict(c *Cache) {fmt.Println("Evicting by fifo strtegy")
}
// lru.go: 具体策略
package mainimport "fmt"type Lru struct {
}func (l *Lru) evict(c *Cache) {fmt.Println("Evicting by lru strtegy")
}
// lfu.go: 具体策略
package mainimport "fmt"type Lfu struct {
}func (l *Lfu) evict(c *Cache) {fmt.Println("Evicting by lfu strtegy")
}
// cache.go: context
package maintype Cache struct {storage      map[string]stringevictionAlgo EvictionAlgocapacity     intmaxCapacity  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 mainfunc 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

相关文章:

  • 四、MySQL之DML DQL
  • VisualSVN Server下载安装和使用方法、服务器搭建、使用TortoiseSvn将项目上传到云端服务器、各种错误解决方法
  • Springfox Swagger2从入门到精通
  • 【算法专题】动态规划之子数组和子串系列
  • 信息安全认证首选CISP-PTE
  • uniapp报错:export { render, staticRenderFns, recyclableRender, components }
  • docker 体验怀旧游戏(魂斗罗等)
  • pcl+vtk(十四)vtkCamera相机简单介绍
  • Hadoop3.x学习笔记
  • ISO27001认证:企业与个人发展的必备之选
  • [学习笔记]刘知远团队大模型技术与交叉应用L4-Prompt-learning Delta-learning
  • Vue 3.0中Treeshaking特性(详细解析)
  • 06 BGP 基础报文状态
  • Dubbo源码解析第一期:如何使用Netty4构建RPC
  • 某马头条——day11+day12
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • CSS实用技巧干货
  • Django 博客开发教程 16 - 统计文章阅读量
  • Javascript Math对象和Date对象常用方法详解
  • JAVA之继承和多态
  • Promise初体验
  • vue-cli在webpack的配置文件探究
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 基于遗传算法的优化问题求解
  • 无服务器化是企业 IT 架构的未来吗?
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 与 ConTeXt MkIV 官方文档的接驳
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • (vue)页面文件上传获取:action地址
  • (ZT)薛涌:谈贫说富
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (九)One-Wire总线-DS18B20
  • (十三)Maven插件解析运行机制
  • (一) springboot详细介绍
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .Net 4.0并行库实用性演练
  • .Net 8.0 新的变化
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • @AliasFor注解
  • @Validated和@Valid校验参数区别
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [17]JAVAEE-HTTP协议
  • [2019/05/17]解决springboot测试List接口时JSON传参异常
  • [AIGC 大数据基础]hive浅谈
  • [AIGC] 开源流程引擎哪个好,如何选型?
  • [BT]小迪安全2023学习笔记(第15天:PHP开发-登录验证)
  • [BUG]Datax写入数据到psql报不能序列化特殊字符
  • [bug总结]: Feign调用GET请求找不到请求体实体类