设计模式- 策略模式(Strategy Pattern)结构|原理|优缺点|场景|示例

                                     设计模式(分类)        设计模式(六大原则)   

    创建型(5种)        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

    结构型(7种)        适配器模式        装饰器模式        代理模式        ​​​​​​外观模式      桥接模式        组合模式       享元模式

    行为型(11种)      策略模式        模板方法模式        观察者模式        迭代器模式        责任链模式        命令模式

                                   备忘录模式          状态模式          访问者模式        中介者模式


设计模式中的策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装在一个单独的类中,使得它们可以互相替换。策略模式使得算法可以在运行时根据需要动态地改变,同时客户端代码可以通过统一的接口调用不同的策略实现。

模式结构

  1. 策略接口(Strategy Interface)

    • 定义所有支持的策略或算法所共有的方法签名,这是所有具体策略类的抽象父类或接口。
  2. 具体策略类(Concrete Strategies)

    • 每个具体策略类实现了策略接口,并提供了算法的具体实现。
    • 在具体策略类中包含了算法的详细逻辑。
  3. 上下文(Context)

    • 上下文是使用策略的对象,它维持对策略对象的引用,并定义了如何使用策略的方法。
    • 上下文可以根据需求改变策略,通常是通过策略接口设置具体的策略对象。

工作原理

  • 客户端:创建并配置上下文对象,指定要使用的具体策略。
  • 上下文:根据客户端的配置,保存一个指向具体策略对象的引用,并在需要执行策略时调用策略接口定义的方法。
  • 具体策略:执行实际的算法或行为。

优缺点

优点
  • 开放封闭原则:策略模式允许在不修改现有代码的基础上新增策略。
  • 多态性:客户端通过策略接口调用方法,无需关注具体实现细节,增强了代码的灵活性和可扩展性。
  • 解耦:策略模式将算法从使用它的上下文中解耦出来,便于算法的独立管理和测试。
缺点
  • 策略类数量增多:随着策略数量的增加,可能会产生大量的策略类。
  • 上下文需了解策略:虽然上下文不用关心策略的具体实现,但是它至少需要知道有哪些策略可供选择,并能够适配不同的策略。

适用场景

  • 系统需要多种算法解决同一问题,且在运行时可以动态切换算法
  • 算法的实现可以相互独立,互不影响
  • 希望避免使用多重条件判断(例如 switch-case 或 if-else)来选择算法

代码示例(以Java为例)

// 抽象策略接口
public interface DiscountStrategy {
    double getDiscount(double price);
}

// 具体策略类 - 无折扣策略
public class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public double getDiscount(double price) {
        return price;
    }
}

// 具体策略类 - 普通会员折扣策略
public class NormalMemberDiscountStrategy implements DiscountStrategy {
    @Override
    public double getDiscount(double price) {
        return price * 0.95; // 九五折
    }
}

// 具体策略类 - VIP会员折扣策略
public class VIPDiscountStrategy implements DiscountStrategy {
    @Override
    public double getDiscount(double price) {
        return price * 0.85; // 八五折
    }
}

// 上下文类 - 订单类,使用策略来计算折扣后的价格
public class Order {
    private DiscountStrategy discountStrategy;

    public Order(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public void setDiscountStrategy(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public double calculateFinalPrice(double originalPrice) {
        return discountStrategy.getDiscount(originalPrice);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Order orderWithoutDiscount = new Order(new NoDiscountStrategy());
        System.out.println("No discount applied: " + orderWithoutDiscount.calculateFinalPrice(100));

        Order normalOrder = new Order(new NormalMemberDiscountStrategy());
        System.out.println("Normal member discount applied: " + normalOrder.calculateFinalPrice(100));

        Order vipOrder = new Order(new VIPDiscountStrategy());
        System.out.println("VIP member discount applied: " + vipOrder.calculateFinalPrice(100));
    }
}

代码示例(以Python为例)

# 策略接口
from abc import ABC, abstractmethod

class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: float) -> None:
        pass

# 具体策略类
class CreditCardPayment(PaymentStrategy):
    def __init__(self, card_number: str, cvv: str):
        self.card_number = card_number
        self.cvv = cvv

    def pay(self, amount: float) -> None:
        print(f"Paid {amount} using credit card ({self.card_number})")

class PayPalPayment(PaymentStrategy):
    def __init__(self, account_id: str):
        self.account_id = account_id

    def pay(self, amount: float) -> None:
        print(f"Paid {amount} using PayPal account ({self.account_id})")

# 上下文
class ShoppingCart:
    def __init__(self, payment_strategy: PaymentStrategy):
        self.payment_strategy = payment_strategy

    def set_payment_strategy(self, strategy: PaymentStrategy) -> None:
        self.payment_strategy = strategy

    def checkout(self, total_amount: float) -> None:
        print(f"Checking out with total amount: {total_amount}")
        self.payment_strategy.pay(total_amount)

# 客户端代码
cart = ShoppingCart(CreditCardPayment("1234567890123456", "123"))
cart.checkout(100.00)

cart.set_payment_strategy(PayPalPayment("buyer@example.com"))
cart.checkout(200.00)

在这个示例中:

  • PaymentStrategy是策略接口,定义了支付方法pay
  • CreditCardPaymentPayPalPayment是具体策略类,实现了支付方式。
  • ShoppingCart是上下文,持有一个支付策略对象,并在其checkout方法中调用策略对象的pay方法来完成支付。根据需要,可以随时更改支付策略。

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

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

相关文章

应用在防蓝光显示器中的LED防蓝光灯珠

相比抗蓝光眼镜、防蓝光覆膜、软体降低蓝光强度这些“软”净蓝手段,通过对LED的发光磷粉进行LED背光进行技术革新,可实现硬件“净蓝”。其能够将90%以上的有害蓝光转换为450nm以上的长波低能光线,从硬件的角度解决了蓝光危害眼睛的问题&#…

python+django校园社交高校交友网站2x7r5.

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行,将系统所使用到的表以及数据存储到MySQL数据库中,方便对数据进行操作本课题基于WEB的开发平台,设计的基本思路是: 前端:vue.jselementui 框架&#…

【机器学习】深度神经网络(DNN):原理、应用与代码实践

深度神经网络(DNN):原理、应用与代码实践 一、深度神经网络(DNN)的基本原理二、DNN的优缺点分析三、DNN的代码实践四、总结与展望 在人工智能与机器学习的浪潮中,深度神经网络(Deep Neural Netw…

Spring Boot 集成 EasyExcel 3.x

Spring Boot 集成 EasyExcel 3.x Spring Boot 集成 EasyExcel 3.x 本章节将介绍 Spring Boot 集成 EasyExcel(优雅实现Excel导入导出)。 🤖 Spring Boot 2.x 实践案例(代码仓库) 介绍 EasyExcel 是一个基于 Java 的、…

【注解和反射】什么时候类会和不会被初始化?

继上一篇博客【注释和反射】类加载的过程-CSDN博客 目录 四、什么时候类会被初始化(主动引用)? 测试 五、什么情况下不会发生类的初始化(被动引用)? 测试 四、什么时候类会被初始化(主动引用…

<网络> HTTP

目录 前言: 一、再谈协议 (一)认识URL (二)Encode 和 Decode 二、HTTP 协议 (一)协议格式 (二)见一见请求 (三)见一见响应 三、模拟实现响…

模块化 DeFi L2 “Mode” 整合 Covalent Network(CQT),以获 Web3 最大数据集的支持

Covalent Network(CQT),作为 Web3 领先的数据层,宣布其统一 API 将与 Mode 集成,以加快其基于以太坊构建的专注于 DeFi 的模块化 Layer2 方案的数据访问速度。这一战略合作将通过为开发者提供更强大的工具和能力&#…

论文浅尝 | LoRA: 大模型的低秩适配

笔记整理:陈一林,东南大学硕士,研究方向为不确定知识图谱规则学习 链接:https://arxiv.org/abs/2106.09685 1、动机 自然语言处理的一个重要范式包括在通用领域数据上进行大规模预训练,然后对特定任务或领域进行适应性…

`THREE.AudioAnalyser` 音频分析

demo案例 THREE.AudioAnalyser 音频分析 入参 (Input Parameters): audio: 一个 THREE.Audio 实例,代表要分析的音频。fftSize: 快速傅里叶变换(FFT)的大小,用于确定分析的精度和频率分辨率。smoothingTimeConstant: 平滑时间…

[lesson58]类模板的概念和意义

类模板的概念和意义 类模板 一些类主要用于存储和组织数据元素 类中数据组织的方式和数据元素的具体类型无关 如:数组类、链表类、Stack类、Queue类等 C中将模板的思想应用于类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能。 C中的类模板…

如何通过cURL库实现远程控制插座

如何通过cURL库实现远程控制插座呢? 本文描述了使用cURL库调用HTTP接口,实现控制插座,即插即用,先插入插座,再接电器,实现远程控制。 可选用产品:可根据实际场景需求,选择对应的规格…

开源文本嵌入模型M3E

进入正文前,先扯点题外话 这两天遇到一个棘手的问题,在用 docker pull 拉取镜像时,会报错: x509: certificate has expired or is not yet valid 具体是下面👇这样的 rootDS918:/volume2/docker/xiaoya# docker pul…

油猴脚本:bing 搜索结果居中

文章目录 效果预览脚本使用步骤安装油猴脚本添加脚本 效果预览 脚本 // UserScript // name bing居中 // namespace http://tampermonkey.net/ // version 2024-04-24 // description try to take over the world! // author You // match http…

牛客 题解

文章目录 day4_17**BC149** **简写单词**思路:模拟代码: dd爱框框思路:滑动窗口(同向双指针)代码: 除2!思路:模拟贪心堆代码: day4_17 BC149 简写单词 https://www.now…

缓存神器-JetCache

序言 今天和大家聊聊阿里的一款缓存神器 JetCache。 一、缓存在开发实践中的问题 1.1 缓存方案的可扩展性问题 谈及缓存,其实有许多方案可供选择。例如:Guava Cache、Caffine、Encache、Redis 等。 这些缓存技术都能满足我们的需求,但现…

CPDA|0到1突破:构建高效数据分析体系的秘密武器

在现今信息爆炸的时代,数据已经渗透到了我们生活的方方面面,成为了决策、创新和竞争优势的关键。因此,构建一套高效的数据分析体系,对于企业和个人而言,都是至关重要的。那么,如何在众多的数据海洋中脱颖而…

自动化立体库安全使用管理制度

导语 大家好,我是智能仓储物流技术研习社的社长,老K。专注分享智能仓储物流技术、智能制造等内容。 新书《智能物流系统构成与技术实践》 完整版文件和更多学习资料,请球友到知识星球 【智能仓储物流技术研习社】自行下载 关于自动化立体库安…

Visual Studio导入libtorch(Cuda版)

Visual Studio导入libtorch(Cuda版) 一、安装 官网:https://pytorch.org/get-started/locally/ 相应地选择并下载 二、环境变量配置 解压zip,得到libtorch文件夹,将libtorch\lib和libtorch\bin对应路径添加到系统环…

如何把视频中的画面保存为图片?免费的工具不用白不用

在数字化时代,截取视频中的珍贵瞬间成为了人们创作、分享和保存回忆的重要方式。 那么,如何迅速捕捉视频中的精彩画面,留存美好瞬间呢?有人说直接截图就可以,如果直接截图就可以,小编就不用写这篇文章了&a…

Redis 安装及配置教程(Windows)【安装】

文章目录 一、简介一、 下载1. GitHub 下载2. 其它渠道 二、 安装1. ZIP2. MSI 软件 / 环境安装及配置目录 一、简介 Redis 官网地址:https://redis.io/   Redis 源码地址:https://github.com/redis/redis   Redis 官网安装地址(无Windo…
最新文章