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

【设计模式】行为型模式(二):策略模式、命令模式

行为型模式(二):策略模式、命令模式

  • 3.策略模式(Strategy)
    • 3.1 示例
      • 3.1.1 定义策略接口
      • 3.1.2 实现具体策略
      • 3.1.3 定义上下文类
      • 3.1.4 客户端代码
      • 3.1.5 输出结果
    • 3.2 总结
      • 3.2.1 优点
      • 3.2.2 缺点
  • 4.命令模式(Command)
    • 4.1 组成部分
    • 4.2 示例
      • 4.2.1 命令接口
      • 4.2.2 具体命令实现
      • 4.2.3 接收者
      • 4.2.4 调用者
      • 4.2.5 客户端
      • 4.2.6 输出结果
    • 4.3 总结
      • 4.3.1 优点
      • 4.3.2 缺点

3.策略模式(Strategy)

策略模式Strategy)是一种行为设计模式,它使你能在运行时改变对象的行为。下面是策略模式的几个关键点:

  • 定义一组算法:策略模式定义了一组可互换的算法(或行为)。这些算法封装在独立的类中,每个类实现一个特定的算法。
  • 封装变化:将变化的部分从不变的部分中分离出来,封装成独立的类,这样可以更容易地扩展和维护。
  • 运行时选择算法:客户端可以根据需要在运行时选择不同的算法(策略)来执行特定任务。

3.1 示例

假设你正在开发一个电商系统,需要根据不同的促销策略计算订单的最终价格。你可以定义一个 PromotionStrategy 接口,然后为不同的促销策略实现该接口,例如:

  • FixedDiscountStrategy:固定金额折扣
  • PercentageDiscountStrategy:百分比折扣
  • NoDiscountStrategy:无折扣

在订单类中,你可以使用 PromotionStrategy 接口来计算最终价格,并在运行时根据需要选择不同的策略。

3.1.1 定义策略接口

首先,定义一个策略接口 PromotionStrategy,该接口声明了一个计算折扣价格的方法 calculateDiscount

public interface PromotionStrategy {double calculateDiscount(double originalPrice);
}

3.1.2 实现具体策略

接下来,实现不同的促销策略,例如 固定金额折扣百分比折扣无折扣

public class FixedDiscountStrategy implements PromotionStrategy {private double discountAmount;public FixedDiscountStrategy(double discountAmount) {this.discountAmount = discountAmount;}@Overridepublic double calculateDiscount(double originalPrice) {return originalPrice - discountAmount;}
}public class PercentageDiscountStrategy implements PromotionStrategy {private double discountRate;public PercentageDiscountStrategy(double discountRate) {this.discountRate = discountRate;}@Overridepublic double calculateDiscount(double originalPrice) {return originalPrice * (1 - discountRate);}
}public class NoDiscountStrategy implements PromotionStrategy {@Overridepublic double calculateDiscount(double originalPrice) {return originalPrice;}
}

FixedDiscountStrategyPercentageDiscountStrategyNoDiscountStrategy 实现了 PromotionStrategy 接口,分别实现了固定金额折扣、百分比折扣和无折扣。

3.1.3 定义上下文类

上下文类 Order 使用 PromotionStrategy 接口来计算最终价格。上下文类可以在运行时选择不同的策略。

public class Order {private double originalPrice;private PromotionStrategy promotionStrategy;public Order(double originalPrice, PromotionStrategy promotionStrategy) {this.originalPrice = originalPrice;this.promotionStrategy = promotionStrategy;}public double getFinalPrice() {return promotionStrategy.calculateDiscount(originalPrice);}public void setPromotionStrategy(PromotionStrategy promotionStrategy) {this.promotionStrategy = promotionStrategy;}
}

3.1.4 客户端代码

客户端代码可以根据需要选择不同的促销策略,并计算订单的最终价格。

public class Client {public static void main(String[] args) {double originalPrice = 100.0;// 固定金额折扣PromotionStrategy fixedDiscountStrategy = new FixedDiscountStrategy(10.0);Order order1 = new Order(originalPrice, fixedDiscountStrategy);System.out.println("Fixed Discount: " + order1.getFinalPrice());// 百分比折扣PromotionStrategy percentageDiscountStrategy = new PercentageDiscountStrategy(0.2);Order order2 = new Order(originalPrice, percentageDiscountStrategy);System.out.println("Percentage Discount: " + order2.getFinalPrice());// 无折扣PromotionStrategy noDiscountStrategy = new NoDiscountStrategy();Order order3 = new Order(originalPrice, noDiscountStrategy);System.out.println("No Discount: " + order3.getFinalPrice());// 动态更改策略order1.setPromotionStrategy(percentageDiscountStrategy);System.out.println("Changed to Percentage Discount: " + order1.getFinalPrice());}
}

客户端代码创建不同的策略对象,并将它们传递给 Order 对象,计算最终价格。还可以在运行时动态更改策略。

3.1.5 输出结果

Fixed Discount: 90.0
Percentage Discount: 80.0
No Discount: 100.0
Changed to Percentage Discount: 80.0

3.2 总结

3.2.1 优点

  • 灵活性:可以在运行时动态选择算法。
  • 扩展性:新增策略时,只需实现新的策略类,无需修改现有代码。
  • 代码复用:不同的上下文可以共享相同的策略。

3.2.2 缺点

  • 类的数量增加:每增加一个策略,就需要增加一个类。
  • 客户端需要知道所有策略:客户端需要了解所有可用的策略,并选择合适的策略。

4.命令模式(Command)

命令模式Command)是一种行为设计模式,它将请求封装成一个对象,从而使你能够用不同的请求、队列或者请求日志来参数化其他对象。命令模式也支持可撤销的操作。

在这里插入图片描述

4.1 组成部分

  • 命令对象:封装了一个请求,包括执行该请求所需的所有信息(例如,接收者、方法、参数等)。
  • 接收者:实际执行命令的对象。
  • 调用者:请求的发起者,它将命令对象传递给接收者。
  • 客户端:创建命令对象并将其设置到调用者中。

4.2 示例

假设我们正在开发一个智能家居系统,用户可以通过 遥控器 控制不同的设备(如 风扇 等)。我们可以使用命令模式来实现这个功能。

4.2.1 命令接口

首先,定义一个命令接口 Command,声明一个执行命令的方法 execute

public interface Command {void execute();
}

4.2.2 具体命令实现

接下来,实现不同的命令,例如控制灯的开关和控制风扇的开关。

// 开灯
public class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.turnOn();}
}// 关灯
public class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.turnOff();}
}// 开风扇
public class FanOnCommand implements Command {private Fan fan;public FanOnCommand(Fan fan) {this.fan = fan;}@Overridepublic void execute() {fan.turnOn();}
}// 关闭风扇
public class FanOffCommand implements Command {private Fan fan;public FanOffCommand(Fan fan) {this.fan = fan;}@Overridepublic void execute() {fan.turnOff();}
}

LightOnCommandLightOffCommandFanOnCommandFanOffCommand 实现了 Command 接口,分别控制灯和风扇的开关。

4.2.3 接收者

接收者是 实际执行命令的对象,例如灯和风扇。

public class Light {public void turnOn() {System.out.println("Light is on");}public void turnOff() {System.out.println("Light is off");}
}public class Fan {public void turnOn() {System.out.println("Fan is on");}public void turnOff() {System.out.println("Fan is off");}
}

LightFan 是实际执行命令的对象。

4.2.4 调用者

调用者是 请求的发起者,它将命令对象传递给接收者。

public class RemoteControl {private Command onCommand;private Command offCommand;public RemoteControl(Command onCommand, Command offCommand) {this.onCommand = onCommand;this.offCommand = offCommand;}public void pressOnButton() {onCommand.execute();}public void pressOffButton() {offCommand.execute();}
}

RemoteControl 是请求的发起者,它将命令对象传递给接收者并执行命令。

4.2.5 客户端

客户端代码 创建不同的命令对象,并将它们设置到 RemoteControl 中,通过调用 RemoteControl 的方法来执行命令。

public class CommandPatternDemo {public static void main(String[] args) {Light light = new Light();Fan fan = new Fan();Command lightOn = new LightOnCommand(light);Command lightOff = new LightOffCommand(light);Command fanOn = new FanOnCommand(fan);Command fanOff = new FanOffCommand(fan);RemoteControl remoteControl = new RemoteControl(lightOn, lightOff);remoteControl.pressOnButton(); // 输出: Light is onremoteControl.pressOffButton(); // 输出: Light is offremoteControl = new RemoteControl(fanOn, fanOff);remoteControl.pressOnButton(); // 输出: Fan is onremoteControl.pressOffButton(); // 输出: Fan is off}
}

4.2.6 输出结果

Light is on
Light is off
Fan is on
Fan is off

通过这个例子,你可以看到命令模式如何将请求的发送者和接收者解耦,使代码更加灵活和可扩展。

4.3 总结

4.3.1 优点

  • 解耦:命令模式将请求的发送者和接收者解耦,使两者不直接依赖。
  • 扩展性:可以很容易地增加新的命令,而不需要修改现有的代码。
  • 支持撤销操作:命令对象可以存储执行前的状态,从而支持撤销操作。

4.3.2 缺点

  • 类的数量增加:每个命令都需要一个具体的命令类。
  • 复杂性增加:引入了多个对象和接口,可能会使系统变得更复杂。

相关文章:

【设计模式】行为型模式(二):策略模式、命令模式

行为型模式(二):策略模式、命令模式 3.策略模式(Strategy)3.1 示例3.1.1 定义策略接口3.1.2 实现具体策略3.1.3 定义上下文类3.1.4 客户端代码3.1.5 输出结果 3.2 总结3.2.1 优点3.2.2 缺点 4.命令模式(Com…...

STM32中断系统

目录 一、中断的基本概念 二、NVIC 1.NVIC的概念 2、NVIC的组成 3、NVIC的应用 4.NVIC的结构 三、外部中断EXTI 1.外部中断的概念 2.EXTI基本结构 四、EXTI外部中断的配置流程 1.开启APB2中的GPIO口/AFIO时钟 2.GPIO配置成输入模式 3.AFIO选择中断引脚 4.EXTI初始…...

window的Anaconda Powershell Prompt 里使用linux 命令

在 Windows 的 Anaconda Powershell Prompt 中使用 Linux 命令,可以通过以下几种方法来实现: 1. 使用 Git Bash 安装 Git for Windows 后,它会包含 Git Bash,允许在 Windows 上使用许多 Linux 命令。 步骤: 安装 Gi…...

Lisp 语言入门教程(一)

Lisp(“LISt Processing”)是一种古老而强大的编程语言,特别适合处理符号数据和列表。Lisp 是一种以括号和递归见长的语言,它启发了许多编程范式。以下是一个基础教程,帮助你快速了解 Lisp 的基本语法和功能。 1. 认识…...

Git - Think in Git

记录一些使用Git时的一些想法 区的概念 当 clone 仓库代码到本地后四个区相同 当编辑代码后,工作区 与其余三个区不同 当使用 add 将修改的代码暂存后,索引区与 工作区 相同 当使用 commit 将修改的代码提交后,仓库区 与 索引区 和 工作区 相…...

jmeter常用配置元件介绍总结之用linux服务器压测

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之用linux服务器压测 1.编写测试脚本2.执行测试脚本 1.编写测试脚本 在linux服务器上进行压测,由于是没有界面的,因此我们可以先在界面上把压测脚本写好: 如图:我这里简单的写…...

VL210-Q4 适用于USB延长线 扩展坞

VL210芯片技术文档 一、概述 VL210是一款由VIA Technologies(威盛电子)生产的第四代先进USB 3.0 Hub控制器。它集成了多种先进技术和功能,适用于各种USB集线器应用,如独立的USB集线器、笔记本/Ultrabook停靠点/port-replicators…...

怎么样绑定域名到AWS(亚马逊云)服务器

1,拿着你买的域名去亚马逊申请一个证书。申请证书分两种,一种是去亚马逊后台填域名手动申请 ,另一种是通过API来申请,类似如下代码: 2、证验证书。有两种方式:一种是通过邮件,另一种去到域名提供…...

Clickhouse集群新建用户、授权以及remote权限问题

新建用户 create user if not exists user on cluster 集群名称 IDENTIFIED WITH plaintext_password BY 密码;给用户授查询、建表、删表的权限 GRANT create table,select,drop table ON 数据库实例.* TO user on cluster 集群名称 ;在其他节点下用户建本地表成功&#…...

OPENCV 检测直线[opencv--3]

opencv中集成了很多好用的函数,比如霍夫变换检测直线的函数,当然,考虑到看我文章的人水平,我这里只讲讲如何使用这个函数,和怎么调节其中的参数 先把运行效果PO出来吧 #include "CV_ERROR.h" #include &q…...

FFmpeg 4.3 音视频-多路H265监控录放C++开发十三.2:avpacket中包含多个 NALU如何解析头部分析

前提: 注意的是:我们这里是从avframe转换成avpacket 后,从avpacket中查看NALU。 在实际开发中,我们有可能是从摄像头中拿到 RGB 或者 PCM,然后将pcm打包成avframe,然后将avframe转换成avpacket&#xff0…...

【MATLAB】目标检测初探

文章目录 0 前言1 目标检测概述2 算法实践2.1 YOLO v22.2 YOLO v3 3 项目实践3.1 项目背景和数据集3.2 实践结果3.3 算法对比 4 工具箱与数据标注5 总结 0 前言 之前因为项目原因,做了一个基于YOLOv5实现目标检测的程序,是基于Python做的,直接…...

SpringCloud 微服务消息队列灰度方案 (RocketMQ 4.x)

目录 背景遇到的问题 RocketMQ 基础基础消息模型扩展后的消息模型部署模型相关概念点 方案对比影子Topic的方案Tag的方案UserProperty的方案影子Group的方案灰度分区的方案方案对比 灰度分区方案设计适配只有部分灰度的情况所做的功能扩展消费者(无灰度)…...

厘清标准差和标准误:因果推断的统计学基础

标准差,指 一次抽样中 个体取值间的离散程度,反映了 个体取值对样本均值的代表性。 标准误,指 多次抽样中 样本均值间的离散程度,反映了 样本均值对总体均值的代表性。 公众号原文-厘清标准差和标准误:因果推断的统计…...

GESP4级考试语法知识(贪心算法(二))

排队接水2代码&#xff1a; #include<iostream> #include<cstdio> #include<algorithm> using namespace std; struct people {int num;int time; }; people s[1001]; int n,r,a[1001]; double sum,ave; bool cmp(people x,people y) {return x.time<y.t…...

MATLAB 使用教程 —— 命令窗口输入命令,工作区显示变量

命令在命令窗口输入变量在工作区显示 MATLAB 桌面包含的面板如下&#xff1a; 当前文件夹 - 此面板允许访问项目文件夹和文件。命令窗口 - 这是主要区域&#xff0c;用户在命令行中输入命令&#xff0c;命令提示符(>>).工作区 - 工作区显示所有变量&#xff0c;无论是创…...

LeetCode 热题100(八)【二叉树】(3)

目录 8.11二叉树展开为链表&#xff08;中等&#xff09; 8.12从前序与中序遍历序列构造二叉树&#xff08;中等&#xff09; 8.13路径总和III&#xff08;中等&#xff09; 8.14二叉树的最近公共祖先&#xff08;中等&#xff09; 8.15二叉树中的最大路径和&#xff08;困…...

uniapp h5实现录音

使用npm安装 npm install recorder-core引入Recorder库 可以使用import、require、html script等你适合的方式来引入js文件&#xff0c;下面的以import为主要参考&#xff0c;其他引入方式根据文件路径自行调整一下就可以了。 //必须引入的Recorder核心&#xff08;文件路径是…...

字节跳动Android面试题汇总及参考答案(80+面试题,持续更新)

Android 四大组件是什么? Android 四大组件分别是 Activity、Service、Broadcast Receiver 和 Content Provider。 Activity 是 Android 应用中最基本的组件,用于实现用户界面。它可以包含各种视图控件,如按钮、文本框等。一个 Activity 通常对应一个屏幕的内容。用户可以通…...

【go从零单排】通道select、通道timeout、Non-Blocking Channel Operations非阻塞通道操作

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 select 语句是 Go 的一种控制结构&#xff0c;用于等待多个通道操作。它类似于 s…...

Umi-OCR插件终极指南:如何选择最适合你的文字识别方案

Umi-OCR插件终极指南&#xff1a;如何选择最适合你的文字识别方案 【免费下载链接】Umi-OCR_plugins Umi-OCR 插件库 项目地址: https://gitcode.com/gh_mirrors/um/Umi-OCR_plugins 还在为文档扫描、图片文字提取效率低下而烦恼吗&#xff1f;Umi-OCR插件库为你提供了全…...

OpenClaw日志分析:QwQ-32B任务执行效率监控

OpenClaw日志分析&#xff1a;QwQ-32B任务执行效率监控 1. 为什么需要监控OpenClaw任务执行效率 去年冬天&#xff0c;我部署了一个自动整理会议纪要的OpenClaw工作流。起初运行得很顺利&#xff0c;直到某天早上发现它漏掉了三场重要会议的记录。检查日志才发现&#xff0c;…...

基于Matlab的正态云模型花卉特征提取:从理论到代码实现

257.基于matlab的正态云模型花卉特征提取&#xff0c;用正向正态云发生器和逆向正态云发生器来模拟花卉的部分特征提取 程序已调通&#xff0c;可直接运行在花卉研究领域&#xff0c;准确提取花卉特征对于花卉分类、品种识别等工作至关重要。今天咱们来聊聊基于Matlab的正态云模…...

Petalinux-build --sdk卡在assimp?手动下载源码并集成到Yocto构建系统的完整指南

解决Petalinux构建SDK时assimp源码下载失败的深度实践指南 当你在Ubuntu 18.04环境下使用Vivado 2021.2进行Petalinux开发时&#xff0c;执行petalinux-build --sdk命令可能会意外卡在assimp组件上。这种问题通常源于网络连接不稳定导致构建系统无法自动下载第三方依赖库。本文…...

高效解析快递地址:Java实现智能识别省市区与楼栋单元户室

1. 快递地址解析的痛点与Java解决方案 每天处理成千上万的快递地址是电商和物流企业最头疼的问题之一。我见过太多这样的场景&#xff1a;客服人员手动复制粘贴地址信息&#xff0c;运营团队熬夜整理Excel表格&#xff0c;配送系统因为地址格式混乱而频频出错。这些问题的根源都…...

TVM终极模型剪枝指南:如何快速实现结构化与非结构化剪枝

TVM终极模型剪枝指南&#xff1a;如何快速实现结构化与非结构化剪枝 想要让深度学习模型跑得更快、占用更少内存&#xff1f;TVM的模型剪枝功能就是你的最佳选择&#xff01;&#x1f680; 本文为你带来TVM剪枝的完整指南&#xff0c;从基础概念到实际应用&#xff0c;让你快速…...

Periphery终极部署指南:Docker和Bazel构建的完整说明

Periphery终极部署指南&#xff1a;Docker和Bazel构建的完整说明 【免费下载链接】periphery A tool to identify unused code in Swift projects. 项目地址: https://gitcode.com/gh_mirrors/pe/periphery Periphery是一款强大的Swift代码分析工具&#xff0c;专门用于…...

3步搞定B站音频提取:BilibiliDown开源工具的终极指南

3步搞定B站音频提取&#xff1a;BilibiliDown开源工具的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi…...

Ollama + DeepSeek + 芋道框架 + SearXNG 本地联网搜索完整教程

1. 环境准备与检查 在开始之前,请确保你的环境满足以下条件: 1.1 硬件要求 内存:建议至少8GB可用内存(运行7B模型需要约4-6GB) 硬盘:DeepSeek模型文件约4-5GB空间 CPU/GPU:如有NVIDIA GPU可加速推理(可选) 1.2 软件要求 操作系统:Windows 10/11、macOS、Linux均可 …...

AI超清画质增强作品集:3倍放大修复,让模糊图片重获新生

AI超清画质增强作品集&#xff1a;3倍放大修复&#xff0c;让模糊图片重获新生 1. 从模糊到高清的视觉革命 你是否遇到过这样的情况&#xff1a;翻出多年前的老照片&#xff0c;却发现画面模糊不清&#xff1b;从网上下载的图片分辨率太低&#xff0c;放大后全是马赛克&#…...