2026/2/20 14:35:29
网站建设
项目流程
镇平微网站建设,wordpress 首页大图,asp网站配置,一级a做爰片免费网站下载文章目录0. 个人感悟1. 概念2. 适配场景2.1 适合的场景2.2 常见场景举例3. 实现方法3.1 实现思路3.2 UML类图3.3 代码示例4. 优缺点4.1 优点4.2 缺点5. 源码分析0. 个人感悟
命令模式核心是将请求或者操作封装成对象。那么就可以基于这些对象进行额外操作#xff0c;比如队列…文章目录0. 个人感悟1. 概念2. 适配场景2.1 适合的场景2.2 常见场景举例3. 实现方法3.1 实现思路3.2 UML类图3.3 代码示例4. 优缺点4.1 优点4.2 缺点5. 源码分析0. 个人感悟命令模式核心是将请求或者操作封装成对象。那么就可以基于这些对象进行额外操作比如队列记录、日志、撤销恢复等实际工作中对于任务队列其实已经有很多成熟的框架不过万变不离其宗理解命令模式对于其它知识(比如三方件、架构)的学习还是很有帮助的1. 概念英文定义(《设计模式可复用面向对象软件的基础》)Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or long requests, and support undoable operations.中文翻译将一个请求封装为一个对象从而使你可以用不同的请求对客户进行参数化对请求排队或记录请求日志以及支持可撤销的操作。理解请求封装将做什么操作和谁来做执行者分离参数化可以像传递参数一样传递命令对象延迟执行命令可以在创建后的某个时间点执行可撤销/重做通过记录命令历史实现操作回退2. 适配场景2.1 适合的场景解耦调用者和接收者需要将请求的发起者和执行者解耦时支持撤销/重做需要实现操作的撤销和重做功能任务队列/日志需要将请求排队、记录日志或延迟执行2.2 常见场景举例遥控器控制家电不同按钮触发不同设备的不同操作餐厅点餐系统订单作为命令厨师作为接收者文本编辑器撤销/重做功能线程池任务调度将任务封装为命令对象游戏控制玩家输入映射到游戏角色的不同动作3. 实现方法3.1 实现思路定义命令接口声明执行命令的抽象方法通常包含execute()和undo()创建具体命令类实现命令接口关联接收者对象定义接收者类实际执行操作的对象创建调用者/请求者类持有命令对象并触发执行客户端组装创建命令对象并设置给调用者3.2 UML类图![[命令模式_UML.png]]角色说明Command命令接口声明执行操作的接口ConcreteCommand具体命令绑定接收者和动作Receiver接收者知道如何执行请求的具体操作Invoker调用者持有命令对象并触发执行Client客户端创建具体命令并设置接收者3.3 代码示例背景: 遥控器控制家电,可以遥控灯、电视灯家具命令接口:publicinterfaceCommand{/** * description 执行 * author bigHao * date 2026/1/20 **/voidexecute();/** * description 撤销 * author bigHao * date 2026/1/20 **/voidundo();}灯的接受者和具体命令publicclassLightReceiver{/** * description 开灯 * author bigHao * date 2026/1/20 **/publicvoidon(){System.out.println(开灯了);}/** * description 关灯 * author bigHao * date 2026/1/20 **/publicvoidoff(){System.out.println(关灯了);}}publicclassLightOnCommandimplementsCommand{privateLightReceiverlightReceiver;publicLightOnCommand(LightReceiverlightReceiver){this.lightReceiverlightReceiver;}Overridepublicvoidexecute(){lightReceiver.on();}Overridepublicvoidundo(){lightReceiver.off();}}publicclassLightOffCommandimplementsCommand{privateLightReceiverlightReceiver;publicLightOffCommand(LightReceiverlightReceiver){this.lightReceiverlightReceiver;}Overridepublicvoidexecute(){lightReceiver.off();}Overridepublicvoidundo(){lightReceiver.on();}}电视接受者和命令:publicclassTVReceiver{/** * description 开机 * author bigHao * date 2026/1/20 **/publicvoidon(){System.out.println(电视开了);}/** * description 关机 * author bigHao * date 2026/1/20 **/publicvoidoff(){System.out.println(电视关了);}}publicclassTVOnCommandimplementsCommand{privateTVReceiverreceiver;publicTVOnCommand(TVReceiverreceiver){this.receiverreceiver;}Overridepublicvoidexecute(){receiver.on();}Overridepublicvoidundo(){receiver.off();}}publicclassTVOffCommandimplementsCommand{privateTVReceiverreceiver;publicTVOffCommand(TVReceiverreceiver){this.receiverreceiver;}Overridepublicvoidexecute(){receiver.off();}Overridepublicvoidundo(){receiver.on();}}遥控器:publicclassRemoteController{publicstaticfinalintINIT_COMMAND_NUM5;privateCommand[]onCommands;privateCommand[]offCommands;privateCommandundoCommand;publicRemoteController(){onCommandsnewCommand[INIT_COMMAND_NUM];offCommandsnewCommand[INIT_COMMAND_NUM];for(inti0;iINIT_COMMAND_NUM;i){onCommands[i]newNoCommand();offCommands[i]newNoCommand();}}publicvoidsetOnCommand(intno,CommandonCommand,CommandoffCommand){onCommands[no]onCommand;offCommands[no]offCommand;}publicvoidon(intno){onCommands[no].execute();// 记录当前操作undoCommandonCommands[no];}publicvoidoff(intno){offCommands[no].execute();// 记录当前操作undoCommandoffCommands[no];}publicvoidundo(){undoCommand.undo();}}测试:publicclassClient{publicstaticfinalintLIGHT_NO0;publicstaticfinalintTV_NO1;staticvoidmain(){RemoteControllerremoteControllernewRemoteController();LightReceiverlightReceivernewLightReceiver();LightOnCommandlightOnCommandnewLightOnCommand(lightReceiver);LightOffCommandlightOffCommandnewLightOffCommand(lightReceiver);// 按键0是灯开关remoteController.setOnCommand(LIGHT_NO,lightOnCommand,lightOffCommand);System.out.println( 按下开灯键位 );remoteController.on(LIGHT_NO);System.out.println( 按下关灯键位 );remoteController.off(LIGHT_NO);System.out.println( 按下撤销键 );remoteController.undo();TVReceivertvReceivernewTVReceiver();TVOnCommandtvOnCommandnewTVOnCommand(tvReceiver);TVOffCommandtvOffCommandnewTVOffCommand(tvReceiver);// 按键1是灯开关remoteController.setOnCommand(TV_NO,tvOnCommand,tvOffCommand);System.out.println( 按下开机键位 );remoteController.on(TV_NO);System.out.println( 按下关机键位 );remoteController.off(TV_NO);System.out.println( 按下撤销键 );remoteController.undo();}}输出: 按下开灯键位 开灯了 按下关灯键位 关灯了 按下撤销键 开灯了 按下开机键位 电视开了 按下关机键位 电视关了 按下撤销键 电视开了4. 优缺点4.1 优点高内聚低耦合调用者与接收者解耦调用者无需知道接收者的具体实现命令对象内聚性高每个命令专注于一个具体操作复用性与可扩展性易于扩展新命令只需实现Command接口命令可复用同一命令可在不同上下文中使用维护性易于维护和修改修改具体操作只需修改对应命令类支持宏命令可将多个命令组合成复杂操作稳定性与可靠性支持事务可批量执行命令并支持回滚支持撤销/重做通过命令历史记录实现4.2 缺点复杂性增加类数量增多每个命令都需要一个具体类系统复杂度提高增加了间接层次性能开销内存占用每个命令都需要创建对象执行效率间接调用可能比直接调用稍慢5. 源码分析Java标准库中Runnable相关实现是简化的命令模式java.lang.Runnable接口// Runnable就是命令接口publicinterfaceRunnable{publicabstractvoidrun();// execute()方法}// Thread作为InvokerThreadthreadnewThread(()-System.out.println(Running command));thread.start();// 触发命令执行角色分析:Command命令接口Runnable接口它定义了run()方法相当于命令模式中的执行方法。ConcreteCommand具体命令实现了Runnable接口的类例如我们通过匿名内部类、Lambda表达式或者具体类实现的run方法中的具体逻辑。Receiver接收者可以是Ru实际执行操作的对象。通常Runnable的实现会调用其他对象接收者的方法。Invoker调用者/请求者调用命令的对象。在Java中Thread类就是一个典型的调用者它接收一个Runnable命令并在适当的时机调用其run方法。参考韩顺平 Java设计模式张维鹏 Java设计模式之行为型命令模式java_my_life《JAVA与模式》之命令模式