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

漫谈设计模式 [18]:策略模式

引导性开场

菜鸟:老鸟,我最近在做一个项目,需要根据用户选择的不同方式计算折扣。现在我用一堆 if-else 来实现,感觉代码越来越臃肿,维护起来也很麻烦。有没有什么更好的方法?

老鸟:听起来这是一个典型的需要策略模式来解决的问题。你听说过策略模式吗?

菜鸟:策略模式?没怎么听说过。它能解决我现在的问题吗?

老鸟:当然可以,策略模式可以帮你把不同的计算逻辑分开,这样代码既简洁又容易维护。我们可以一步一步来,先从简单的例子开始。

渐进式介绍概念

老鸟:想象一下,你去一家咖啡店,店里提供了不同的支付方式:现金支付、信用卡支付和移动支付。每种支付方式都有不同的处理方式,但最终目的是一样的——完成支付。这就像策略模式中的不同策略,每个策略都是一个独立的算法实现。

菜鸟:这样说我大概明白了。那在代码中该怎么实现呢?

老鸟:我们可以用Python来实现。首先,我们定义一个支付策略的接口,然后实现几个具体的支付策略。

Python代码示例,逐步展开

老鸟:先定义一个策略接口:

from abc import ABC, abstractmethod

class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

菜鸟:这里用到了 abc 模块和 abstractmethod 装饰器,这是在做什么?

老鸟:这是在定义一个抽象类和抽象方法。PaymentStrategy 是一个抽象类,它定义了一个抽象方法 pay,任何具体的支付策略类都需要实现这个方法。

菜鸟:明白了,那具体的支付策略怎么写?

老鸟:接下来,我们实现几种具体的支付策略:

class CashPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Paying {amount} using cash.")

class CreditCardPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Paying {amount} using credit card.")

class MobilePayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Paying {amount} using mobile payment.")

菜鸟:这样每种支付方式都有了自己的实现,那怎么用这些策略呢?

老鸟:我们还需要一个上下文类,它会使用一个策略来完成支付。

class PaymentContext:
    def __init__(self, strategy: PaymentStrategy):
        self._strategy = strategy

    def execute_payment(self, amount):
        self._strategy.pay(amount)

菜鸟:上下文类 PaymentContext 持有一个策略实例,并在 execute_payment 方法中调用策略的 pay 方法。这样我们可以灵活地切换不同的支付策略。

问题与反思

菜鸟:这看起来不错,但如果我把所有支付方式都写在一个类里,然后用 if-else 来选择支付方式,不也可以实现吗?

老鸟:确实可以,但如果支付方式越来越多,if-else 会使代码变得很冗长,维护起来也很麻烦。而使用策略模式,每种支付方式都是独立的类,代码更清晰,扩展性更好。你只需要新增一个策略类,而不需要修改现有的代码。

优势与适用场景

老鸟:策略模式的优势在于它遵循了开放-封闭原则,对扩展开放,对修改封闭。它适用于需要在运行时根据不同条件选择不同算法的场景,比如支付方式、排序算法、文件压缩等。

菜鸟:听起来很有道理,我以后会尝试用策略模式来优化代码。

常见误区与优化建议

老鸟:不过要注意,策略模式也有一些常见误区。比如,不要滥用策略模式,对于简单的条件判断,策略模式反而会增加复杂度。另外,策略类可能会有很多相似的代码,可以考虑使用组合等方式来减少重复代码。

总结与延伸阅读

老鸟:今天我们通过一个简单的例子,逐步了解了策略模式的概念、实现以及它的优势和适用场景。策略模式让我们可以灵活地切换不同的算法,同时保持代码的简洁和可维护性。如果你对设计模式感兴趣,可以读读《设计模式:可复用面向对象软件的基础》和《Head First 设计模式》,这两本书对设计模式有很好的介绍。

菜鸟:谢谢老鸟,我学到了很多!接下来我会多看看设计模式的资料,尝试在项目中应用。

老鸟:不客气,有问题随时来找我。下一步,你可以看看工厂模式和观察者模式,它们在实际开发中也非常有用。

希望这篇对话式的博客能帮助你更好地理解策略模式,祝你编码愉快!


http://www.kler.cn/news/302952.html

相关文章:

  • ISO 21434与网络安全管理系统(CSMS)的协同作用
  • Java 入门指南:Java 并发编程 —— 同步工具类 Exchanger(交换器)
  • 学生请假管理系统
  • pytest钩子函数
  • Ubuntu22.04安装nginx
  • SpringBoot项目用Aspose-Words将Word转换为PDF文件正常显示中文的正确姿势
  • RP2040 C SDK clocks时钟源配置使用
  • 【Kubernetes】K8s 的鉴权管理(二):基于属性 / 节点 / Webhook 的访问控制
  • 《PhysDiff: Physics-Guided Human Motion Diffusion Model》ICCV2023
  • Rust使用Actix-web和SeaORM库开发WebAPI通过Swagger UI查看接口文档
  • 若依框架使用MyBatis-Plus中的baseMapper的方法报错Invalid bound statement (not found):
  • 中电金信:金融级数字底座“源启”:打造新型数字基础设施 筑牢千行百业数字化转型发展基石
  • sponge创建的服务与dtm连接使用etcd、consul、nacos进行服务注册与发现
  • GPT-4与ChatGPT:人工智能对话的新时代【含国内可用gpt】
  • 红帽7—tomcat的部署方法
  • Unity3D Android多渠道极速打包方案详解
  • [000-01-008].第05节:OpenFeign高级特性-请求/响应压缩
  • 【油猴脚本】00003案例 Tampermonkey油猴脚本引入css 库,油猴脚本css库的使用
  • web基础之RCE
  • Ansible简单部署与使用
  • Debian项目实战——环境搭建篇
  • ctfshow-web入门-sql注入(web244-web247)error 报错注入
  • java项目之基于Spring Boot智能无人仓库管理源码(springboot+vue)
  • 《JavaEE进阶》----14.<SpringMVC配置文件实践之【验证码项目】>
  • 【聊聊AI编程必不可少的NLTK及其punkt、punkt_tab安装】
  • Python | Leetcode Python题解之第395题至少有K个重复字符的最长子串
  • WRF-LES与PALM微尺度气象大涡模拟、PALM静态数据预备、PALM驱动数据预报、PALM模拟
  • 软件交付文档
  • NAND NOR FLASH闪存产品的学习记录
  • 充电桩平台的优惠券功能如何设计