Python中的策略模式:解锁编程的新维度
引言
策略模式是一种行为型设计模式,允许算法独立于使用它的客户端而变化。这使得我们可以根据不同的情况选择不同的算法或策略来解决问题,从而增强系统的灵活性。在日常开发中,策略模式常用于处理多种算法或行为之间的切换,比如在电子商务系统中实现多种支付方式,在游戏开发中实现角色的不同攻击模式等。
基础语法介绍
核心概念
- 策略接口(Strategy Interface):定义了一组算法应该具有的公共接口。
- 具体策略类(Concrete Strategy Classes):实现了策略接口,每个类代表一种具体的算法或策略。
- 上下文(Context):使用策略接口,并且可以在运行时动态地改变所使用的具体策略类。
基本语法规则
在Python中,实现策略模式通常涉及定义一个抽象基类(或接口),然后创建多个继承自该基类的具体类来表示不同的策略。上下文对象负责调用策略对象的方法。
from abc import ABC, abstractmethodclass Strategy(ABC):@abstractmethoddef do_algorithm(self, data):passclass ConcreteStrategyA(Strategy):def do_algorithm(self, data):return sorted(data)class ConcreteStrategyB(Strategy):def do_algorithm(self, data):return reversed(sorted(data))class Context:def __init__(self, strategy: Strategy):self._strategy = strategydef set_strategy(self, strategy: Strategy):self._strategy = strategydef do_some_business_logic(self, data):result = self._strategy.do_algorithm(data)print(f"Sorting data with {type(self._strategy).__name__}: {result}")if __name__ == "__main__":context = Context(ConcreteStrategyA())context.do_some_business_logic([1, 3, 2])context.set_strategy(ConcreteStrategyB())context.do_some_business_logic([1, 3, 2])
基础实例
假设我们需要为一个在线商店提供多种排序商品的方式(按价格、销量等)。这里我们可以使用策略模式来实现这一需求。
问题描述
用户希望能够在浏览商品列表时,根据自己的偏好选择不同的排序方式。
代码示例
from abc import ABC, abstractmethodclass ProductSorter(ABC):@abstractmethoddef sort_products(self, products):passclass PriceSorter(ProductSorter):def sort_products(self, products):return sorted(products, key=lambda p: p.price)class PopularitySorter(ProductSorter):def sort_products(self, products):return sorted(products, key=lambda p: p.popularity, reverse=True)class Product:def __init__(self, name, price, popularity):self.name = nameself.price = priceself.popularity = popularityproducts = [Product("Laptop", 1200, 5),Product("Headphones", 150, 3),Product("Smartphone", 800, 7)
]context = Context(PriceSorter())
sorted_by_price = context.sort_products(products)
print("Sorted by price:", [p.name for p in sorted_by_price])context.set_strategy(PopularitySorter())
sorted_by_popularity = context.sort_products(products)
print("Sorted by popularity:", [p.name for p in sorted_by_popularity])
进阶实例
在复杂环境下,我们可能需要考虑更多的因素,例如根据不同条件选择不同的策略组合。接下来,我们将通过一个更复杂的例子来进一步探讨策略模式的应用。
问题描述
某电商平台需要根据用户的购物历史、会员等级等因素动态调整推荐算法。
高级代码实例
class User:def __init__(self, id, purchase_history, membership_level):self.id = idself.purchase_history = purchase_historyself.membership_level = membership_leveldef get_recommendation_strategy(user: User):if user.membership_level == "premium":return PremiumUserRecommendationStrategy()else:return RegularUserRecommendationStrategy()class RecommendationStrategy(ABC):@abstractmethoddef recommend_products(self, user: User):passclass RegularUserRecommendationStrategy(RecommendationStrategy):def recommend_products(self, user: User):# Implement logic for regular userspassclass PremiumUserRecommendationStrategy(RecommendationStrategy):def recommend_products(self, user: User):# Implement logic for premium userspass# Example usage
user = User(1, ["laptop", "smartphone"], "premium")
strategy = get_recommendation_strategy(user)
recommended_products = strategy.recommend_products(user)
print("Recommended products:", recommended_products)
实战案例
问题描述
在一个真实的电商项目中,我们需要根据用户的地理位置信息,动态调整商品的价格显示策略。例如,对于海外用户,显示美元价格;而对于国内用户,则显示人民币价格。
解决方案
引入策略模式,根据用户的地理位置信息动态选择合适的定价策略。
代码实现
from abc import ABC, abstractmethodclass PricingStrategy(ABC):@abstractmethoddef calculate_price(self, base_price):passclass USDollarPricingStrategy(PricingStrategy):def calculate_price(self, base_price):return base_price * 1.15 # Assuming exchange rate of 1.15 USD/CNYclass CNYPricingStrategy(PricingStrategy):def calculate_price(self, base_price):return base_priceclass Product:def __init__(self, name, base_price):self.name = nameself.base_price = base_pricedef get_pricing_strategy(user_location):if user_location == "US":return USDollarPricingStrategy()else:return CNYPricingStrategy()# Example usage
product = Product("Smartphone", 800)
strategy = get_pricing_strategy("US")
final_price = strategy.calculate_price(product.base_price)
print(f"Final price for {product.name} in US: {final_price} USD")strategy = get_pricing_strategy("CN")
final_price = strategy.calculate_price(product.base_price)
print(f"Final price for {product.name} in CN: {final_price} CNY")
扩展讨论
除了上述应用场景之外,策略模式还可以应用于许多其他领域,如日志记录、错误处理等。在实际工作中,我们可以根据项目的具体需求灵活运用策略模式,以达到最佳的效果。此外,结合其他设计模式(如工厂模式、装饰者模式等),可以进一步提升代码的灵活性和可维护性。
相关文章:
Python中的策略模式:解锁编程的新维度
引言 策略模式是一种行为型设计模式,允许算法独立于使用它的客户端而变化。这使得我们可以根据不同的情况选择不同的算法或策略来解决问题,从而增强系统的灵活性。在日常开发中,策略模式常用于处理多种算法或行为之间的切换,比如…...
ara::core::Future::then()的概念和使用方法
1. 概念 在ara::core::Future的上下文中,then()是一种用于处理异步操作结果的机制。一个Future代表一个尚未完成的异步计算,它最终会产生一个结果或者一个错误。then()方法允许你在Future完成时注册一个回调函数(或者说后续操作)…...

九、5 USART串口数据包
数据包作用:把一个个单独的数据给打包起来,将同一批的数据进行打包和分割,方便接收方进行识别,方便我们进行多字节的数据通信。 1、串口收发HEX数据包 (1)数据包的格式是个人规定的,如以FF为包…...

SQL第12课——联结表
三点:什么是联结?为什么使用联结?如何编写使用联结的select语句 12.1 联结 SQL最强大的功能之一就是能在数据查询的执行中联结(join)表。联结是利用SQL的select能执行的最重要的操作。 在使用联结前,需要了解关系表…...

CentOS7 虚拟机操作系统安装及相关配置教程
1、安装虚拟机 在VMware《主页》界面中点击《创建新的虚拟机》按钮: 选择你准备好的ISO文件,点击下一步: 然后填写虚拟机的名称以及虚拟机将来保存的位置: 再次下一步,填写虚拟机磁盘大小: 继续下一步&…...

『网络游戏』窗口基类【06】
创建脚本:WindowRoot.cs 编写脚本: 修改脚本:LoginWnd.cs 修改脚本:LoadingWnd.cs 修改脚本:ResSvc.cs 修改脚本:LoginSys.cs 运行项目 - 功能不变 本章结束...
04_23 种设计模式之《单例模式》
文章目录 一、单例模式基础知识单例模式有 3 个特点: 单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。这种模式通常用于管理共享资源,如…...

视频加字幕用什么软件最快?12款工具快速添加字幕!
对于大多数同学来讲,剪辑中比较头疼的就是如何给视频加字幕和唱词啦,特别是用Pr或者FCXP等专业剪辑软件,加字幕也是特别费时的,哪怕是有批量添加的功能orz... 虽然关于这方面的内容已经很多啦,但是真正全面的内容还特…...

C++:string (用法篇)
文章目录 前言一、string 是什么?二、C语法补充1. auto2. 范围for 三、string类对象的常见构造1. Construct string object2. String destructor3. operator 四、string迭代器相关1. begin与end1)begin2)end3)使用 2. rbegin 与 r…...
力扣随机题
最接近原点的K个点 题目 973. 最接近原点的 K 个点 - 力扣(LeetCode) 思路 这就是一道排序题,直接根据公式排序,然后返回对应范围的数组就行了 代码 public int[][] kClosest(int[][] points, int k) {Arrays.sort(points, n…...

CSS样式基础样式选择器(案例+代码实现+效果图)
目录 1.css样式的规则 2.引入css样式的方式 1)行内式 2)内嵌式 3)外链式 1-link导入 2-import导入 4)总 3.css基础选择器 1)标签选择器 案例:使用标签选择器编写一个圆 1.代码 2.效果 2)类选择器 案例:使用类选择器为div添加背景色 1.代码 2.效果 3)id…...
Linux系统编程—I/O缓冲区(C语言实现)
I/O缓冲区 进程的I/O缓冲区机制是计算机操作系统中一个重要的概念,它涉及到数据在内存和外设之间的传输。以下是关于进程的I/O缓冲区机制的详细解释: 1.定义与作用 定义:I/O缓冲区是指在内存里开辟的一块区域,用来存放接收用户输…...

MySQL多表查询:行子查询
先看我的表数据 dept表 emp表 行子查询 子查询返回的结果是一行(可以是多列), 这种子查询称为行子查询 常用的操作符: , <>, IN, NOT IN 例子1. 查询与“张无忌” 的薪资及直属领导相同的员工信息 拆解成两个问题 a. 查询"张无忌"…...

.NET CORE程序发布IIS后报错误 500.19
发布IIS后浏览时报错误500.19,同时配置文件web.config的路径中也存在问号“?”。 可能原因:没有安装运行时...
Qt 6 相比 Qt 5 的主要提升与更新
自从 Qt 6 发布以来,作为 Qt 框架的一个重大版本更新,它在多个核心方面进行了深度优化和改进。与 Qt 5 相比,Qt 6 不仅提升了性能,还改进了对现代硬件和图形 API 的支持,并增强了开发者的工作流程。本文将详细介绍 Qt …...
【数据结构】介绍
介绍数据结构 数据结构是计算机科学中重要的概念,是指组织和管理数据的方式。它涉及到数据的存储、操作和访问等操作。数据结构可以分为线性结构、树形结构和图形结构等。 线性结构是最简单的数据结构之一(本玄也是这样觉得(* ̄▽ ̄*))&#…...
论医疗类系统全国运营推广策略
一、线上推广 搜索引擎优化(SEO)- 重点策略 持续更新网站内容,包括系统功能介绍、成功案例、行业新闻等,提高网站的权重和流量。进行搜索引擎优化(SEO),确定与医疗机构辅助系统相关的关键词&a…...

Redis入门第一步:认识Redis与快速安装配置
认识Redis与快速安装配置🍃 Redis是什么🐲 1.Redis的背景🎍 Redis(Remote Dictionary Server)译为"远程字典服务",它是一款基于内存实现的键值型 NoSQL 数据库, 通常也被称为数据结…...

ES postman操作全量修改,局部修改,删除
全量修改 修改需要调用的url 地址是http://192.168.1.108:9200/shopping/_doc/1001,调用方法使用put 只修改指定的需求的内容的请求方式 post方式就是局部修改 http://192.168.1.108:9200/shopping/_update/1001,请求方式post 上图是只修改id 为1001数…...

社区交流礼仪 | 提问的艺术
唠唠闲话 2021 年通过 Julia 社区了解到开源,自此开始融入开源社区,学习和体验这种独特的协作模式与交流文化,受益良多。本篇文章为开源新手必读,文章中探讨的交流模式,不仅对参与开源项目的协作有所帮助,…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...

【记录坑点问题】IDEA运行:maven-resources-production:XX: OOM: Java heap space
问题:IDEA出现maven-resources-production:operation-service: java.lang.OutOfMemoryError: Java heap space 解决方案:将编译的堆内存增加一点 位置:设置setting-》构建菜单build-》编译器Complier...