Golang学习笔记_39——策略模式

news/2025/2/28 15:56:10/

Golang学习笔记_36——装饰器模式
Golang学习笔记_37——外观模式
Golang学习笔记_38——享元模式


文章目录

      • 一、核心概念
        • 1. 定义
        • 2. 解决的问题
        • 3. 核心角色
        • 4. 类图
      • 二、特点分析
      • 三、适用场景
        • 1. 支付系统
        • 2. 数据压缩
        • 3. 游戏AI
        • 4. 折扣计算
      • 四、代码示例(Go语言)
        • 场景:电商会员折扣系统
        • 执行结果
      • 五、高级应用
        • 1. 策略工厂模式
        • 2. 组合策略
      • 六、与其他模式对比
      • 七、总结


一、核心概念

1. 定义

策略模式是一种行为型设计模式,通过定义一系列可互换的算法,并将其封装为独立类,使得算法可以独立于客户端而变化。核心思想是将算法与使用场景解耦,支持运行时动态切换策略。

2. 解决的问题
  • 算法频繁切换:需要根据不同条件选择不同算法(如支付方式、折扣策略)
  • 消除条件判断:避免大量if-elseswitch-case语句
  • 算法复用性:同一算法被多个客户端调用(如排序、压缩算法)
3. 核心角色
角色作用
Strategy策略接口,定义算法的公共方法(如Execute()
ConcreteStrategy具体策略实现类(如支付宝支付、微信支付)
Context上下文类,持有策略引用并执行算法
4. 类图

<a class=策略模式类图" />

@startuml
class Context {- strategy: Strategy+ SetStrategy()+ ExecuteStrategy()
}interface Strategy {+ Execute()
}class ConcreteStrategyA {+ Execute()
}class ConcreteStrategyB {+ Execute()
}Context o--> Strategy
Strategy <|.. ConcreteStrategyA
Strategy <|.. ConcreteStrategyB
@enduml

二、特点分析

优点

  1. 开闭原则:新增策略无需修改现有代码
  2. 代码清晰:消除复杂条件判断,提升可维护性
  3. 灵活扩展:运行时动态切换策略(如游戏AI行为切换)

缺点

  1. 类数量膨胀:每个策略需单独定义类
  2. 客户端耦合:客户端需了解所有策略的存在

三、适用场景

1. 支付系统
  • 策略接口PaymentStrategy
  • 具体策略:信用卡、支付宝、微信支付
  • 动态切换:用户下单时选择支付方式
// 策略接口
type PaymentStrategy interface {Pay(amount float64) string
}// 具体策略:支付宝
type AlipayStrategy struct{}
func (a *AlipayStrategy) Pay(amount float64) string {return fmt.Sprintf("支付宝支付%.2f元", amount)
}
2. 数据压缩
  • 策略接口CompressionStrategy
  • 具体策略:ZIP、RAR、7z算法
  • 按需选择:根据文件类型自动选择压缩算法
// 策略接口
type CompressionStrategy interface {Compress(file string) []byte
}// 具体策略:ZIP压缩
type ZipStrategy struct{}
func (z *ZipStrategy) Compress(file string) []byte {return []byte("ZIP压缩后的数据")
}
3. 游戏AI
  • 策略接口AIBehavior
  • 具体策略:进攻、防御、逃跑模式
  • 动态调整:根据玩家血量切换NPC行为
// 策略接口
type AIBehavior interface {Act() string
}// 具体策略:防御模式
type DefenseBehavior struct{}
func (d *DefenseBehavior) Act() string {return "进入防御状态"
}
4. 折扣计算
  • 策略接口DiscountStrategy
  • 具体策略:普通用户9折、VIP用户8折
  • 组合策略:叠加满减和折扣(见高级应用)

四、代码示例(Go语言)

场景:电商会员折扣系统

在这里插入图片描述

package strategydemo// 策略接口
type DiscountStrategy interface {Calculate(price float64) float64
}// 具体策略:普通会员
type NormalDiscount struct{}
func (n *NormalDiscount) Calculate(price float64) float64 {return price * 0.9 // 9折
}// 具体策略:VIP会员
type VIPDiscount struct{}
func (v *VIPDiscount) Calculate(price float64) float64 {return price * 0.8 // 8折
}// 上下文类
type Order struct {strategy DiscountStrategy
}func (o *Order) SetStrategy(s DiscountStrategy) {o.strategy = s
}func (o *Order) Checkout(price float64) float64 {return o.strategy.Calculate(price)
}// 客户端使用
func TestStrategy() {order := &Order{}// 普通用户order.SetStrategy(&NormalDiscount{})fmt.Printf("普通用户价格: %.2f\n", order.Checkout(100)) // 90.00// 切换为VIP策略order.SetStrategy(&VIPDiscount{})fmt.Printf("VIP用户价格: %.2f\n", order.Checkout(100)) // 80.00
}
执行结果
=== RUN   Test_TestStrategy
普通用户价格: 90.00
VIP用户价格: 80.00
--- PASS: Test_TestStrategy (0.00s)
PASS

五、高级应用

1. 策略工厂模式
// 策略工厂(带注册机制)
type StrategyFactory struct {strategies map[string]DiscountStrategy
}func NewStrategyFactory() *StrategyFactory {return &StrategyFactory{strategies: map[string]DiscountStrategy{"normal": &NormalDiscount{},"vip":    &VIPDiscount{},},}
}// 动态获取策略
func (f *StrategyFactory) GetStrategy(key string) DiscountStrategy {return f.strategies[key]
}// 使用示例
factory := NewStrategyFactory()
order.SetStrategy(factory.GetStrategy("vip"))
2. 组合策略
// 组合折扣(满300减50 + VIP折扣)
type CompositeDiscount struct {strategies []DiscountStrategy
}func (c *CompositeDiscount) Calculate(price float64) float64 {for _, s := range c.strategies {price = s.Calculate(price)}return price
}// 使用示例
composite := &CompositeDiscount{strategies: []DiscountStrategy{&FullReductionStrategy{Threshold: 300, Reduce: 50},&VIPDiscount{},},
}
fmt.Printf("组合折扣价格: %.2f", composite.Calculate(350)) // (350-50)*0.8=240

六、与其他模式对比

模式核心目标关键区别
状态模式对象内部状态改变行为状态转移由内部条件触发
工厂模式创建对象关注对象创建过程
模板方法算法步骤固定通过继承实现代码复用

七、总结

策略模式通过算法封装动态切换,解决了以下问题:

  1. 灵活扩展:新增策略无需修改上下文
  2. 代码复用:相同策略可被多个客户端共享
  3. 条件简化:消除复杂的if-else分支

在Go语言中实现时需注意:

  • 通过接口实现多态,而非继承
  • 使用工厂模式管理策略实例
  • 组合策略实现复杂算法叠加
  • 避免策略类过度细分(如差异过小的策略合并)

http://www.ppmy.cn/news/1575537.html

相关文章

国内短剧系统源码部署小程序体验测评讲解

在移动互联网飞速发展的今天&#xff0c;短剧作为一种新兴的娱乐形式&#xff0c;凭借其短小精悍、内容丰富的特点&#xff0c;迅速赢得了大量用户的青睐。作为一名软件测试人员&#xff0c;我有幸深入体验了一款功能全面、设计精良的短剧小程序。本文将从前端设计、后端功能、…

leetcode203-----移除链表元素

目录 一、题目简介 二、解题思路 三、代码 3.1 直接使用原来的链表来进行移除节点操作 1. 时间复杂度 删除头节点&#xff1a; 删除非头节点&#xff1a; 综合分析&#xff1a; 2. 空间复杂度 总结&#xff1a; 3.2 设置虚拟头节点 时间复杂度&#xff1a; 空间复…

常见锁类型介绍

下面结合代码详细介绍 Mutex、RW Lock、Futex、自旋锁、信号量、条件变量 和 synchronized&#xff0c;并分析它们的适用场景、特点以及为什么这些锁适用于特定场景。我们将从锁的实现机制和性能特点出发&#xff0c;解释其适用性。 1. Mutex&#xff08;互斥锁&#xff09; 代…

AcWing 蓝桥杯集训·每日一题2025

题目链接 : 5437. 拐杖糖盛宴 题意: 有m个不同的糖果和n个不同高度的奶龙, 奶龙可以根据自己的身高去吃糖果,糖果垂直于地面,对于一个糖果都需要让每个奶龙尝试能否吃到,如果吃到则减去相应吃到的长度, 奶龙长高吃掉糖果的长度即可,根据长度进行判断, 分类讨论。 解题思路 : …

英伟达4090显卡ubuntu服务器部署deepseek大模型步骤(vLLM)(未验证)

文章目录 一、环境搭建&#xff08;关键步骤&#xff09;二、模型部署&#xff08;推荐vLLM方案&#xff09;1. 启动OpenAI兼容API服务2. 参数说明 三、API调用&#xff08;完全兼容OpenAI协议&#xff09;四、进阶优化建议五、验证流程附&#xff1a;vLLM与原生HuggingFace性能…

seacmsv9管理员账号+密码注入

Seacms v9 SQL 注入漏洞分析与利用 1. 漏洞概述 Seacms&#xff08;海洋 CMS&#xff09;是一款基于 PHP5.X MySQL 架构的视频点播系统&#xff0c;被广泛用于影视站点管理。在 Seacms v9 版本中&#xff0c;./comment/api/index.php 存在 SQL 注入漏洞&#xff0c;漏洞参数…

本地部署DeepSeek全攻略:Ollama+Chatbox保姆级教程

目录 缘起 为什么需要本地部署&#xff1f; 硬件要求建议&#xff1a; 下载Ollama 安装准备 选择对应的平台下载 下载完成点击安装 install 安装完成后验证 win r打开运行窗口 输入cmd打开命令行窗口 输入ollama&#xff0c;看到有这些输出就代表安装ollama成功啦 …

ubuntu下r8125网卡重启丢失修复案例一则

刚装的一台服务器&#xff0c;ubuntu24.04&#xff0c;主板网卡是r8125&#xff0c;安装服务后会莫名其妙丢失驱动 按照官网的方法下载最新8125驱动包&#xff1a; Realtek 然后卸载驱动 rmmod r8125 然后在驱动包里安装&#xff08;幸好我之前装了build-essential&#x…