首页 > 其他分享 >设计模式:策略模式——行为型模式

设计模式:策略模式——行为型模式

时间:2025-01-13 23:01:00浏览次数:3  
标签:return 策略 float 算法 模式 discount amount 设计模式

目录

主要组成

优点

缺点

使用场景:

示例代码

普通写法:

策略模式:

策略模式与 if-else 的关系:

 区别总结


策略模式(Strategy Pattern)是一种行为型设计模式,旨在通过定义一系列的算法(或策略),将每个算法封装起来,使它们可以互换,并使得算法的变化独立于使用算法的客户端。

主要组成

  1. Context(上下文):上下文类通常持有一个策略对象的引用,并且委托给策略来执行某些具体操作。上下文类通常不直接包含具体的算法,而是与策略接口交互。

  2. Strategy(策略接口):策略接口定义了所有支持的算法的通用接口。不同的策略类实现这个接口,提供不同的具体算法。

  3. ConcreteStrategy(具体策略类):每个具体策略类实现了策略接口,并定义了具体的算法或行为。

优点

  • 开放封闭原则:策略模式使得新的算法可以不修改原有代码的情况下新增,符合开放封闭原则(对扩展开放,对修改封闭)。

  • 避免多重条件语句:策略模式避免了使用大量的if-elseswitch-case语句来选择不同的算法。

  • 增强算法的独立性:将算法独立出来,使得算法可以在不同的上下文中复用。

缺点

  • 客户端必须知道所有的策略并且自行决定使用哪一个策略。

  • 如果策略非常多,那么对于策略的选择可能会变得复杂。

使用场景:

  1. 需要动态改变算法或行为时:例如,根据用户的选择动态切换不同的算法或策略。

  2. 多种算法可以互相替代时:例如,多个支付方式(如信用卡支付、支付宝支付、微信支付等)可以通过策略模式进行切换。

  3. 避免使用复杂的条件语句时:例如,如果有多个条件判断可以决定程序的行为,可以通过策略模式使得代码更加简洁和易于维护。

示例代码

需求:为不同的金额范围(如 100 元、200 元、500 元 等)实现具体的折扣策略。

普通写法:
def get_discount_amount(amount: float) -> float:
    if amount >= 1000:
        return amount * 0.85
    elif amount >= 500:
        return amount * 0.90
    elif amount >= 200:
        return amount * 0.92
    elif amount >= 100:
        return amount * 0.95
    else:
        return amount


if __name__ == "__main__":
    amounts = [90, 150, 250, 600, 1200]
    for amount in amounts:
        discounted_amount = get_discount_amount(amount)

        print(f"原价 {amount} 元,折后价 {discounted_amount} 元")
策略模式:
from abc import ABC, abstractmethod


# 策略接口
class DiscountStrategy(ABC):
    @abstractmethod
    def calculate_discount(self, amount: float) -> float:
        pass


# 具体策略:无折扣
class NoDiscountStrategy(DiscountStrategy):
    def calculate_discount(self, amount: float) -> float:
        return amount


# 具体策略类:100元打95折
class DiscountStrategy100(DiscountStrategy):
    def calculate_discount(self, amount: float) -> float:
        return amount * 0.95


# 具体策略类:200元打92折
class DiscountStrategy200(DiscountStrategy):
    def calculate_discount(self, amount: float) -> float:
        return amount * 0.92


# 具体策略类:500元打9折
class DiscountStrategy500(DiscountStrategy):
    def calculate_discount(self, amount: float) -> float:
        return amount * 0.90


# 具体策略类:1000元以上打8.5折
class DiscountStrategy1000(DiscountStrategy):
    def calculate_discount(self, amount: float) -> float:
        return amount * 0.85


# 上下文类
class DiscountContext:
    def __init__(self, strategy: DiscountStrategy):
        # 持有一个策略对象的引用
        self._strategy = strategy

    def execute_discount(self, amount: float) -> float:
        return self._strategy.calculate_discount(amount)


# 客户端代码:根据金额选择策略
def get_discount_strategy(amount: float) -> DiscountStrategy:
    # 客户端必须知道所有的策略并且自行决定使用哪一个策略。
    if amount >= 1000:
        return DiscountStrategy1000()
    elif amount >= 500:
        return DiscountStrategy500()
    elif amount >= 200:
        return DiscountStrategy200()
    elif amount >= 100:
        return DiscountStrategy100()
    else:
        return NoDiscountStrategy()


# 客户端代码
if __name__ == "__main__":
    # 如明确知道所需策略
    amount = 250
    context = DiscountContext(DiscountStrategy200())
    discounted_amount = context.execute_discount(250)
    print(f"原价 {amount} 元,折后价 {discounted_amount} 元")

    print('-' * 20)

    # 需要动态选取策略
    amounts = [90, 150, 250, 600, 1200]
    for amount in amounts:
        # 获取合适的折扣策略
        strategy = get_discount_strategy(amount)
        # 创建上下文,执行折扣计算
        context = DiscountContext(strategy)
        discounted_amount = context.execute_discount(amount)
        print(f"原价 {amount} 元,折后价 {discounted_amount} 元")

策略模式与 if-else 的关系:

策略模式中,我们的目标是将不同的策略(在这里是折扣策略)封装到不同的策略类中,然后通过上下文类(DiscountContext)来选择合适的策略执行。策略模式本身并不要求在选择策略时完全消除所有的 if-else,但其核心思想是将这些条件判断封装在策略类中,而不是集中在外部逻辑中。

 区别总结
方面策略模式直接使用 if-else
添加新规则只需添加新的策略类,客户端代码稍作调整。需要修改函数。
开闭原则符合开闭原则,对扩展开放,对修改关闭。违反开闭原则,每次修改都需要改动函数。
职责分离折扣逻辑封装在独立的策略类中,职责清晰。折扣逻辑和业务逻辑耦合在一起。
动态切换策略支持运行时动态切换策略,灵活性高。静态逻辑,无法动态调整。
代码复杂度适合复杂场景,代码结构清晰。适合简单场景,规则增多后难以维护。

标签:return,策略,float,算法,模式,discount,amount,设计模式
From: https://blog.csdn.net/fengjingping11/article/details/145124568

相关文章

  • [TypeScript] 实现一个强大的模式匹配
    前言众所不周知,在Rust语言中,有一个强大的语法,模式匹配:fnmain(){letdata=Some(12);matchdata{Some(i)=>println!("{}",i),None=>println!("Nodata"),}}那么在typescript中我们如何为自己实现一个这么好用的语法呢?match.ts//......
  • 单例模式(Singleton Pattern)——游戏开发常用设计模式(一)
    前言单例模式应该是在unity游戏开发中最简单最常用的设计模式之一,无论是管理全局游戏状态、处理资源加载,还是控制音频播放,单例模式都能为我们提供一个简洁的解决方案——确保一个类只有一个实例,并允许在游戏的任何地方轻松访问它。然而,这种便利性也伴随着潜在的风险,比如代码耦合......
  • C#中的设计模式:构建更加优雅的代码
    C#在面向对象编程(OOP)方面的强大支持,我们可以探讨“C#中的设计模式”。这不仅有助于理解如何更好地组织代码,还能提高代码的可维护性和可扩展性。引言设计模式是软件工程中经过实践验证的解决方案模板,它们提供了一种标准化的方法来解决常见的开发问题。对于使用C#进行开发......
  • 如何高效运营OZON:从基础搭建到运营策略
    一、市场分析与定位在开始运营OZON之前,进行市场研究是必不可少的。通过分析市场趋势、竞争对手和目标客户的需求,可以为你的运营策略提供有力的数据支持。使用市场调研工具,了解当前的消费趋势和市场需求,帮助你制定适合的产品和营销策略。了解OZON平台上的主要竞争对手,包括他们......
  • 如何高效运营OZON:从基础搭建到运营策略
    一、市场分析与定位在开始运营OZON之前,进行市场研究是必不可少的。通过分析市场趋势、竞争对手和目标客户的需求,可以为你的运营策略提供有力的数据支持。使用市场调研工具,了解当前的消费趋势和市场需求,帮助你制定适合的产品和营销策略。了解OZON平台上的主要竞争对手,包括他们......
  • C语言:虚拟地址空间及编译模式
    所谓虚拟地址空间,就是程序可以使用的虚拟地址的有效范围。虚拟地址和物理地址的映射关系由操作系统决定,相应地,虚拟地址空间的大小也由操作系统决定,但还会受到编译模式的影响。这节我们先讲解CPU,再讲解编译模式,让大家了解编译器是如何配合CPU来提高程序运行速度的。CPU的......
  • Standards模式和Quirks模式有什么区别?
    Standards模式和Quirks模式在前端开发中的主要区别体现在浏览器如何解释和渲染HTML和CSS。这两种模式是由文档类型(DOCTYPE)声明触发的,对前端开发者和网页设计师来说至关重要。以下是它们之间的主要区别:渲染方式的差异:Standards模式:也称为严格呈现模式,用于呈现遵循最新Web标准......
  • 社群团购项目运营策略的深度剖析:融合链动2+1模式、AI智能名片与S2B2C商城小程序的综合
    摘要:随着互联网技术的飞速发展和消费者购物习惯的不断变化,社群团购作为一种新兴的商业模式,正逐渐成为连接供应商、商家与消费者的重要桥梁。然而,社群团购的成功并非仅限于线上运营,其关键在于项目整体运营的优劣,特别是线上线下融合的综合运营策略。本文旨在深入探讨社群团购项目......
  • 信息时代的消费者行为变迁与应对策略:基于链动2+1模式、AI智能名片及S2B2C商城小程序的
    摘要:随着信息技术的飞速发展与互联网的全面普及,消费者行为模式正在经历深刻变革。在信息大爆炸的背景下,消费者拥有了前所未有的信息获取能力,他们开始独立思考,追求个性化消费体验,并展现出理性消费的趋势。面对这一变化,企业传统的营销策略面临挑战,亟需寻找新的市场切入点和服务模......
  • 深入探究 Go 语言中 Map 和 Slice 未初始化的情况及应对策略
    目录深入探究Go语言中Map和Slice未初始化的情况及应对策略一、问题误区与正确思路二、Map未初始化的情况(一)代码示例与运行结果(二)原因分析(三)Map初始化的重要性三、Slice未初始化的情况(一)代码示例与运行结果(二)原因分析(三)与Map的区别四、总结在Go语言......