Python 如何实现 Strategy 策略设计模式?什么是 Strategy 策略设计模式?

策略模式(Strategy Design Pattern)是一种对象行为型设计模式,它定义了一系列算法,并使得这些算法可以相互替换,使得客户端代码可以独立于算法的变化而变化。策略模式属于对象行为模式。

在这里插入图片描述

主要角色:

  1. 策略接口(Strategy): 定义了所有支持的算法的公共接口。通常由具体策略类实现。

  2. 具体策略类(ConcreteStrategy): 实现了策略接口,提供具体的算法实现。

  3. 环境类(Context): 维持一个对策略对象的引用,并在需要时调用策略对象的算法。通常客户端通过环境类来使用策略。

工作流程:

  1. 客户端创建一个具体的策略对象,实现了策略接口。

  2. 客户端将策略对象传递给环境类。

  3. 环境类在需要执行算法的时候,调用策略对象的算法。

优点:

  • 算法可自由切换: 客户端可以根据需要切换不同的策略,灵活地选择合适的算法。

  • 避免使用多重条件语句: 策略模式可以避免使用过多的条件语句,提高代码的可维护性。

  • 符合开闭原则: 新的算法可以方便地加入到系统中,而不影响现有代码。

Python 示例代码(一):

以下是一个简单的策略模式的示例,假设有一个支付系统,可以选择不同的支付策略:

from abc import ABC, abstractmethod

# 策略接口
class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

# 具体策略类
class CreditCardPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Paying {amount} using Credit Card")

class PayPalPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Paying {amount} using PayPal")

# 环境类
class ShoppingCart:
    def __init__(self, payment_strategy):
        self.payment_strategy = payment_strategy
    
    def checkout(self, amount):
        self.payment_strategy.pay(amount)

# 客户端
credit_card_payment = CreditCardPayment()
paypal_payment = PayPalPayment()

cart1 = ShoppingCart(credit_card_payment)
cart1.checkout(100)

cart2 = ShoppingCart(paypal_payment)
cart2.checkout(150)

在这个例子中,PaymentStrategy 是策略接口,CreditCardPaymentPayPalPayment 是具体的策略类,而 ShoppingCart 是环境类。客户端可以根据需要选择不同的支付策略。


Python 示例代码(二)

让我们考虑一个动物王国的场景,其中有不同种类的动物,每种动物都有自己的叫声。我们可以使用策略模式来模拟这个场景:

from abc import ABC, abstractmethod

# 策略接口
class SoundStrategy(ABC):
    @abstractmethod
    def make_sound(self):
        pass

# 具体策略类
class BarkStrategy(SoundStrategy):
    def make_sound(self):
        return "Woof! Woof!"

class MeowStrategy(SoundStrategy):
    def make_sound(self):
        return "Meow!"

class RoarStrategy(SoundStrategy):
    def make_sound(self):
        return "Roar!"

# 环境类
class Animal:
    def __init__(self, sound_strategy):
        self.sound_strategy = sound_strategy
    
    def make_sound(self):
        return self.sound_strategy.make_sound()

# 客户端
dog = Animal(BarkStrategy())
cat = Animal(MeowStrategy())
lion = Animal(RoarStrategy())

print("Dog says:", dog.make_sound())
print("Cat says:", cat.make_sound())
print("Lion says:", lion.make_sound())

在这个例子中,SoundStrategy 是策略接口,定义了动物叫声的标准。BarkStrategyMeowStrategyRoarStrategy 是具体的策略类,分别模拟了狗、猫和狮子的叫声。Animal 是环境类,它接受一个叫声策略,并在调用 make_sound 时调用相应的策略。

在客户端,你可以为不同的动物选择不同的叫声策略,从而模拟它们各自的叫声行为。

这个例子更加生动,展示了策略模式在真实场景中的一种应用。这种方式使得系统更容易扩展,例如当新的动物种类被引入时,只需添加一个新的策略类即可。


使用该模式应该注意的地方:

使用策略模式时,需要注意一些关键点,以确保模式的有效实施和系统的可维护性。以下是一些建议:

  1. 接口设计: 确保策略接口(抽象策略类)清晰简洁,包含了所有具体策略类应实现的方法。这有助于确保一致性和易于理解。

  2. 灵活性与复杂性的平衡: 策略模式使得算法可以独立变化,但也可能导致类的数目增加。在设计时要平衡灵活性和类的数量,避免过度复杂化。

  3. 运行时切换策略: 考虑系统是否需要在运行时动态切换策略。如果需要,确保环境类(Context)能够接受新的策略并进行切换。

  4. 策略参数化: 确保策略能够接受参数,使得策略的行为可以根据输入参数进行调整。这提高了策略的灵活性。

  5. 合适的使用场景: 策略模式适用于一组算法变体,客户端需要从中选择一个的情况。如果只有一个算法,或者算法数量有限且变动不大,可能不是最适合的模式。

  6. 避免过度使用: 不要在不需要的地方引入策略模式。只有当有多个相关的算法时,而且需要在运行时选择时,才考虑使用策略模式。

  7. 关注性能: 策略模式可能引入一些额外的开销,因为需要通过接口调用来执行算法。在性能敏感的应用中,需要进行评估并选择合适的设计方案。

  8. 适当的文档: 提供适当的文档和注释,以解释每个具体策略的用途和行为。这有助于其他开发人员理解和使用你的代码。

  9. 测试: 对策略模式进行适当的单元测试,确保每个具体策略和整个系统的行为都符合预期。

  10. 考虑与其他模式结合使用: 策略模式可以与其他设计模式结合使用,例如工厂模式、单例模式等,以更好地满足系统需求。

在设计和使用策略模式时,综合考虑这些因素将有助于确保系统的可维护性、灵活性和性能。


本文就到这里了,感谢您的阅读 。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/141093.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

抖音小程序定制开发: 解锁创意,打造独特互动体验

随着抖音平台的崛起,抖音小程序定制开发成为数字创新的关键领域之一。本文将探讨如何通过定制开发,实现独特功能和个性化设计,为用户带来全新的互动体验。 1. 环境搭建 在开始抖音小程序的定制开发之前,首先需要搭建开发环境。…

UBoot

uboot是什么? 嵌入式linux系统启动过程 嵌入式系统上电后先执行uboot、然后uboot负责初始化DDR,初始化Flash,然后将OS从Flash中读取到DDR中,然后启动OS(OS启动后uboot就无用了)uboot是什么,ubo…

【LeetCode刷题笔记】二叉树(一)

102. 二叉树的层序遍历 解题思路: 1. BFS广度优先遍历 ,使用队列,按层访问 解题思路: 2. 前序遍历 , 递归 ,在递归方法参数中,将 层索引

网银转账虚拟生成器在线制作,工商农业邮政建设招商,标签+对话框+画板+快照实现

标签对话框画板快照实现就实现了一个虚拟截图生成器,当然我加了水印了,这个图片你根本盗用不了,图片模版的话网上真的太多了,我这个也是网上找的,自己百度图库搜一下,然后标签记得一定用黑月的透明标签&…

Word转PDF简单示例,分别在windows和centos中完成转换

概述 本篇博客以简单的示例代码分别在Windows和Linux环境下完成Word转PDF的文档转换。 文章提供SpringBoot Vue3的示例代码。 文章为什么要分为Windows和Linux环境? 因为在如下提供的Windows后端示例代码中使用documents4j库做转换,此库需要调用命令行…

如何制作一个有吸引力的电商小程序

随着互联网的快速发展,电商行业也在不断壮大,越来越多的商家开始进入电商领域。在这个竞争激烈的市场中,一个有吸引力的电商小程序能够为商家带来巨大的优势。那么,如何制作一个有吸引力的电商小程序呢?下面我们将以乔…

2023nacos源码解读第2集——nacos-server的启动

nacos 是一个典型的server-client中间件,server这里安装最新的nacos-server 2.3.0-BETA版本 1.docker启动nacos-server 镜像详情参考nacos-docker项目的readme ,很方便,但是官方提供的nacos-server镜像往往可能滞后,且不便于后续…

【Git】第一篇:Git安装(centos)

git查看安装版本 以我自己的centos7.6为例,我们可以输入以下指令查看自己是否安装了git. git --version安装了的话就会显示自己安装的版本。 git 安装 安装很简单,一条命令即可 sudo yum install git -ygit 卸载 sudo yum remove git -y

本地生活直播的下个红利期来了!虚拟直播遇上本地生活擦出新火花

近年来,本地生活直播发展迅猛,作为一种全新的线下实体店营销方式,它比电商直播更贴近消费者的生活需求。比如消费者通过直播购买套餐或消费券,并在实体店核销。这种情况就可以归属于本地生活直播的服务范围。因此,对于…

基于SpringBoot+Vue的高校心理教育管理系统

基于SpringBootVue的高校心理教育管理系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringBootMyBatisVue工具:IDEA/Ecilpse、Navicat、Maven 系统展示 测试列表 测试结果 用户界面 管理员界面 摘要 本文设计并实现了一款…

【Java 进阶篇】JQuery DOM操作:舞动网页的属性魔法

在前端的舞台上,属性操作是我们与HTML元素进行互动的关键步骤之一。而JQuery,这位前端开发的巫师,通过简洁而强大的语法,为我们提供了便捷的属性操作工具。在这篇博客中,我们将深入研究JQuery DOM操作中的属性操作&…

【时间复杂度和空间复杂度】

文章目录 前言时间复杂度大O的渐进表示法推导大O阶方法练习 空间复杂度练习 前言 衡量算法的效率分为两种情况: 1.时间复杂度 2.空间复杂度 时间复杂度 含义:算法中的基本操作的执行次数,为算法的时间复杂度 大O的渐进表示法 计算时间复…

网络安全专用产品有哪些?能一一列举出来吗?

网络安全专用产品是专门为网络安全设计的防护产品。那你知道网络安全专用产品有哪些?这里我们小编就给大家汇总了一下,仅供参考哈! 网络安全专用产品有哪些? 1、数据备份与恢复产品 2、防火墙 3、入侵检测系统 4、入侵防御系统…

IDEA 2023搭建 SpringMVC +FreeMarker+JDBC

1.IDEA的版本,目前最新是2023,要选择旗舰版。笔者曾选择社区版,发现少了很多功能。只能重新安装。 2.安装好以后的第1件事,是设置Maven,并将下载地址改为淘定站,参照这篇一次包会——最新IDEA配置Maven指南…

网络渗透测试(被动扫描)

被动扫描 主要是指的是在目标无法察觉的情况下进行信息搜集。在Google上进行人名的搜素就是一次被动扫描。最经典的被动扫描技术就是"Google Hacking"技术。由于Google退出中国,暂时无法使用。在此介绍三个优秀的信息搜集工具 被动扫描范围 1.企业网络…

Redis应用之二分布式锁2

一、前言 前一篇 Redis应用之二分布式锁 我们介绍了使用SETNX来实现分布式锁,并且还遗留了一个Bug,今天我们对代码进行优化,然后介绍一下Redisson以及数据库的乐观锁悲观锁怎么用。 二、SetNX分布式锁优化后代码 RedisService.java Inven…

Python数据容器之[列表]

Python数据容器 Python中的数据容器: 一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素 每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。 数据容器根据特点的不同,如: 是否支…

Python数据容器(序列操作)

序列 1.什么是序列 序列是指:内容连续、有序。可以使用下标索引的一类数据容器 列表、元组、字符串。均可以视为序列 2.序列的常用操作 - 切片 语法:序列[起始下标:结束下标:步长]起始下标表示从何处开始,可以留空,留空视作从…

python 根据经纬度绘制点图 极投影

参考了python cartopy手动导入地图数据绘制底图/python地图上绘制散点图:Downloading:warnings/散点图添加图里标签_python add_feature-CSDN博客 点的颜色按照时间显示 # -*- coding: utf-8 -*- """ Created on Mon Nov 13 11:32:48 2023"&quo…