首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

设计模式之命令模式

编程知识
2024年09月03日 15:35

命令模式(Command Pattern),给大家的第一感觉,就是给程序发送命令,比如:启动、暂停,然后程序根据接收到的命令直接执行就行。
这样的理解相对来说比较狭义,来看下命令模式官方的定义:
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
一个太狭义,一个又太晦涩。(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )
我对命令模式的理解是这样的:我们将请求参数,以及请求的执行逻辑、依赖对象等,封装在一个对象中,将这个对象推送到执行的引擎中,由执行引擎来驱动执行。我们通过命令模式可以更好的封装逻辑、管理逻辑。

它是面向对象的23种设计模式中的一种,属于行为模式的范围。
我们来看这样的一个例子:

工作接口类

 1 package com.example.demo.learn.pattern.behavior.command;
 2 
 3 /**
 4  * @discription
 5  */
 6 public interface IWorkCommand {
 7 
 8     String getWorkName();
 9 
10     void execute();
11 }

司机工作类

 1 package com.example.demo.learn.pattern.behavior.command;
 2 
 3 import lombok.AllArgsConstructor;
 4 import lombok.extern.slf4j.Slf4j;
 5 
 6 /**
 7  * @discription
 8  */
 9 @AllArgsConstructor
10 @Slf4j
11 public class DriverWork implements IWorkCommand {
12 
13     private String name;
14 
15     @Override
16     public String getWorkName() {
17         return "Driver: " + name;
18     }
19 
20     @Override
21     public void execute() {
22         log.warn("start invoke {} work", getWorkName());
23         log.warn("运送货物到指定目的地");
24         log.warn("打扫汽车卫生");
25         log.warn("将汽车送回停车地点");
26     }
27 }

程序员工作类

 1 package com.example.demo.learn.pattern.behavior.command;
 2 
 3 import lombok.AllArgsConstructor;
 4 import lombok.extern.slf4j.Slf4j;
 5 
 6 /**
 7  * @discription
 8  */
 9 
10 @AllArgsConstructor
11 @Slf4j
12 public class ProgrammerWork implements IWorkCommand{
13 
14     private String name;
15     @Override
16     public String getWorkName() {
17         return "programmer: "+name;
18     }
19 
20     @Override
21     public void execute() {
22         log.warn("start invoke {} work", getWorkName());
23         log.warn("修复昨天遗留的问题.");
24         log.warn("完成今天的开发工作.");
25         log.warn("优化系统性能和稳定性.");
26     }
27 }

执行中心

 1 package com.example.demo.learn.pattern.behavior.command;
 2 
 3 /**
 4  * @discription
 5  */
 6 public class InvokeCenter {
 7     public void invokeWork(IWorkCommand workCommand) {
 8 
 9         workCommand.execute();
10     }
11 }

主类

 1 package com.example.demo.learn.pattern.behavior.command;
 2 
 3 /**
 4  * @discription
 5  */
 6 public class PatternMain {
 7     public static void main(String[] args) {
 8         IWorkCommand programmerWork = new ProgrammerWork("小p");
 9         IWorkCommand driverWork = new DriverWork("小d");
10         InvokeCenter invokeCenter = new InvokeCenter();
11         invokeCenter.invokeWork(driverWork);
12         invokeCenter.invokeWork(programmerWork);
13     }
14 }

输出结果是这样的:

Connected to the target VM, address: '127.0.0.1:52437', transport: 'socket'
15:57:07.856 [main] WARN com.example.demo.learn.pattern.behavior.command.DriverWork - start invoke Driver: 小d work
15:57:07.866 [main] WARN com.example.demo.learn.pattern.behavior.command.DriverWork - 运送货物到指定目的地
15:57:07.866 [main] WARN com.example.demo.learn.pattern.behavior.command.DriverWork - 打扫汽车卫生
15:57:07.866 [main] WARN com.example.demo.learn.pattern.behavior.command.DriverWork - 将汽车送回停车地点
15:57:07.867 [main] WARN com.example.demo.learn.pattern.behavior.command.ProgrammerWork - start invoke programmer: 小p work
15:57:07.867 [main] WARN com.example.demo.learn.pattern.behavior.command.ProgrammerWork - 修复昨天遗留的问题.
15:57:07.868 [main] WARN com.example.demo.learn.pattern.behavior.command.ProgrammerWork - 完成今天的开发工作.
15:57:07.868 [main] WARN com.example.demo.learn.pattern.behavior.command.ProgrammerWork - 优化系统性能和稳定性.
Disconnected from the target VM, address: '127.0.0.1:52437', transport: 'socket'

Process finished with exit code 0

在这个例子中,我们并不直接执行各种具体的工作,而是将他们都封装到一段方法中,由执行引擎统一的来执行。
这段逻辑是不是和通过实例化Thread 的方式,进行多线程操作的逻辑很像?(请参考这篇文章)
没错,在多线程的执行中,就应用到了命令模式。(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )
我们结合命令模式,可以发现这种结构大概有这3个角色:
1、一个抽象的命令接口(抽象类),在这里是 ,他用来约定我们要执行的方法放在哪里,怎么执行。我们一般称之为抽象命令类 Command
2、实现了抽象命令的实现类,在这里是,我们一般通过编写这个类,来实现我们想要的逻辑。我们一般称之为具体命令类 Concrete Command
3、调用者,在这里是,我们一般通过调用者来存储和执行命令,一般也称之为 请求者/调用者 invoker
除此之外还有一个角色
实现者(Receiver),这个角色,在我们的示例中隐藏的有点深,是log对象,也就是命令对象中,真正执行逻辑操作的对象。
注意调用者invoker 是不直接持有实现者的,两者是没有耦合关系的,是通过持有命令对象,间接的持有了调用者,间接的驱动了调用者。这样做既可以让调用者不关心具体的业务(譬如说线程池从来不直接持有执行对象的引用,而只持有对应的执行方法 (run()),由执行方法来组织逻辑和解耦)。
类图大概是这样子:

有些人问,我直接依赖调用者,然后调用调用者的某些方法,来实现我需要的逻辑是否可以,

答案是可以,但是如果第三方想要执行你的这段逻辑、或者你需要将这段逻辑交给第三方去在特定的时机处理执行,你会怎么做呢?
这时候你就需要将你实现的这段逻辑封装到一个对象中,交给其他人,这时候最终又变成了命令模式的体现。

命令模式除了进行解耦,还有一个好处就是可以编排和管理业务逻辑(命令)。
举个例子:有时候我们要做的一个业务包含几件相关的事,事情之间没有先后顺序,
比如我们去超市买一瓶可乐,需要做:
1、拿可乐
2、支付
此时我们就可以将每件事各自封装成一个命令,将整个业务包含的命令,打包丢给执行引擎,这样是不是就很好处理业务了。
A业务要做:a,b,c 三个命令
B业务要做:a,c,d,e 四个命令
我们只要定义每个命令,然后封装好每块业务需要做的几件事(命令),这样面相对象的设计感觉一下子就出来了。

From:https://www.cnblogs.com/jilodream/p/18394876
本文地址: http://shuzixingkong.net/article/1698
0评论
提交 加载更多评论
其他文章 Spring 学习笔记
概述 Spring 是一个企业级 J2EE 应用开发一站式解决方案,其提供的功能贯穿了项目开发的表现层、业务层和持久化层,同时,Spring 可以和其他应用框架无缝整合 Spring 的特性包括以下几个方面: 轻量:Spring 是一个轻量级的框架,其核心 JAR 包的大小均为 1MB 左右。从系统
Spring 学习笔记
WebShell流量特征检测_中国菜刀篇
80后用菜刀,90后用蚁剑,95后用冰蝎和哥斯拉,以phpshell连接为例,本文主要是对这四款经典的webshell管理工具进行流量分析和检测。 什么是一句话木马? 1、定义 顾名思义就是执行恶意指令的木马,通过技术手段上传到指定服务器并可以正常访问,将我们需要服务器执行的命令上传并执行 2、特点
WebShell流量特征检测_中国菜刀篇 WebShell流量特征检测_中国菜刀篇 WebShell流量特征检测_中国菜刀篇
开源问卷调查和考试系统 SurveyKing 安装和使用教程
最近公司又要搞什么满意度调查了,我这个小菜鸟又要头疼了。上次用那个破系统,界面丑不说,功能还少得可怜,搞得我加班到半夜。这回非得找个好用的不可。 正发愁呢,突然想起来前两天同事小王推荐了一个叫 “卷王” 的开源系统,这名字挺有意思的,我还以为是什么 “卷王” 专用的问卷系统呢,后来才知道,这个 “卷
开源问卷调查和考试系统 SurveyKing 安装和使用教程 开源问卷调查和考试系统 SurveyKing 安装和使用教程 开源问卷调查和考试系统 SurveyKing 安装和使用教程
STM32的bootloader探究
OTA OTA(Over-The-Air Technology,空中下载技术)是一种通过无线网络对设备进行远程升级的技术。这种技术最初在PC电脑和移动手机行业中得到应用,近年来在汽车行业中也得到了广泛的应用。 IAP:In-Application Programming (IAP) 是一种使微控制器
STM32的bootloader探究 STM32的bootloader探究 STM32的bootloader探究
AI图像放大工具,图片放大无所不能
AI图像放大工具,如ESRGAN,对于提高由Stable Diffusion生成的AI图像质量至关重要。它们被广泛使用,以至于许多Stable Diffusion的图形用户界面(GUI)都内置了支持。
AI图像放大工具,图片放大无所不能 AI图像放大工具,图片放大无所不能 AI图像放大工具,图片放大无所不能
嵌入式学习路径----------写给大二或者大一
学习路径 课内学习 课程安排有c++、Qt、单片机、数电模电等等 Qt使用c++写,主要就是图形化界面设计开发,具体的其他算法实现就是c++。 单片机程序是用C语言写,控制逻辑,驱动开发等。 单片机课程一上来就STM32可能有些难以理解的地方 可以先从51入手或者arduino等。 Qt就需要设计和
WebShell流量特征检测_蚁剑篇
80后用菜刀,90后用蚁剑,95后用冰蝎和哥斯拉,以phpshell连接为例,本文主要是对这四款经典的webshell管理工具进行流量分析和检测。 什么是一句话木马? 1、定义 顾名思义就是执行恶意指令的木马,通过技术手段上传到指定服务器并可以正常访问,将我们需要服务器执行的命令上传并执行 2、特点
WebShell流量特征检测_蚁剑篇 WebShell流量特征检测_蚁剑篇 WebShell流量特征检测_蚁剑篇
😶‍🌫️ SpringBoot中MongoDB的骚操作用法
不知道大家在工作项目中有没有使用MongoDB,在哪些场景中使用。MongoDB作为NoSQL数据库,不像SQL数据库那样,可以使用Mybatis框架。 如果需要在SpringBoot中使用MongoDB的话,我目前知道有三种方式,第一种是直接使用MongoDB官方的SDK,第二种是使用Spring
😶‍🌫️ SpringBoot中MongoDB的骚操作用法 😶‍🌫️ SpringBoot中MongoDB的骚操作用法 😶‍🌫️ SpringBoot中MongoDB的骚操作用法