南昌网站建设怎么样,赣州英文网站建设,新闻类网站设计,蓝色的网站登录页面模版命令模式(Command)
当我们有一个功能完善的类VideoClass,能够实现视频转码, 视频缓存 等等实际功能.
此时调用者需要依赖用户输入的命令来执行VideoClass中的一个或几个方法函数.
直觉上, 我们会写一个switch-case语句来处理用户输入的命令, 并执行VideoClass中的对应方法, 简单…命令模式(Command)当我们有一个功能完善的类VideoClass,能够实现视频转码, 视频缓存 等等实际功能.此时调用者需要依赖用户输入的命令来执行VideoClass中的一个或几个方法函数.直觉上, 我们会写一个switch-case语句来处理用户输入的命令, 并执行VideoClass中的对应方法, 简单的可以这么做, 但是当用户的命令批量输入, 且要我们记录用户输入的所有命令, 或者要将所有命令都队列化存储之后依次执行时, 我们需要将命令解耦出来, 封装成独立的类, 这就是命令模式.假如我们有如下问题:publicclassCommandPattern{publicstaticvoidmain(String[]args){Stringcommandargs[1];// 用户输入的指令RobotrobotnewRobot();WeaponweaponnewWeapon();// TODO:: 要实现用户批量输入的命令: 变身车辆-发射5次粒子炮-变身人类-发射3发子弹// TODO:: 延迟3分钟发射粒子炮switch(command){casecar:robot.transToCar();// TODO:: 记录日志: 变身车辆// TODO:: 记录变身耗时// 其他操作...casehuman:robot.transToHuman();// TODO:: 记录日志: 变身人类// TODO:: 记录变身耗时// 其他操作...casebullet:weapon.fireBullet();// TODO:: 记录日志: 开火发射子弹// TODO:: 记录发射子弹数量// 其他操作...caseparticle:weapon.fireParticleCannon();// TODO:: 记录日志: 开火发射粒子炮// TODO:: 记录发射粒子炮次数// 其他操作...}}}// 两个真正执行指令对应的功能的类classRobot{publicvoidtransToCar(){System.out.println([robot] 变身一辆车);}publicvoidtransToHuman(){System.out.println([robot] 变身T800);}}classWeapon{publicvoidfireBullet(){System.out.println([武器] 发射子弹);}publicvoidfireParticleCannon(){System.out.println([武器] 发射粒子炮);}}代码中标注TODO的部分, 随着需求的扩展, 会变得越来越臃肿以下是针对以上问题, 命令模式的实现定义命令的统一接口, 所有的命令类都依据接口实现功能// 命令模式的核心, 定义通用的命令接口interfaceCommand{// 执行命令voidexecute();// 获取命令名称用于日志StringgetCommandName();}// 命令一变身车辆绑定Robot接收者classTransToCarCommandimplementsCommand{privatefinalRobotrobot;// 附加记录耗时、日志privatelongstartTime;privatelongendTime;publicTransToCarCommand(Robotrobot){this.robotrobot;}Overridepublicvoidexecute(){startTimeSystem.currentTimeMillis();// 执行接收者的核心逻辑robot.transToCar();endTimeSystem.currentTimeMillis();// 附加逻辑记录日志、耗时log();}OverridepublicStringgetCommandName(){return变身车辆;}privatevoidlog(){System.out.printf([日志] 命令%s执行时间%s耗时%dms%n,getCommandName(),newDate(),endTime-startTime);}}// 命令二发射子弹支持参数发射次数classFireBulletCommandimplementsCommand{privatefinalWeaponweapon;privatefinalinttimes;// 发射次数参数封装privatelongstartTime;privatelongendTime;publicFireBulletCommand(Weaponweapon,inttimes){this.weaponweapon;this.timestimes;}Overridepublicvoidexecute(){startTimeSystem.currentTimeMillis();// 执行带参数的逻辑for(inti0;itimes;i){weapon.fireBullet();}endTimeSystem.currentTimeMillis();log();}OverridepublicStringgetCommandName(){return发射子弹;}privatevoidlog(){System.out.printf([日志] 命令%s次数%d执行时间%s耗时%dms%n,getCommandName(),times,newDate(),endTime-startTime);}}// 命令三 ...// 命令四 ...// 命令五 ...// 命令随着功能类的更新可以无限扩展由于单独命令都进行了封装, 因此可以将命令队列化批量操作, 可以将命令记录日志可以支持更灵活的操作于是, 下面这个类实现将命令存储进队列后依次执行的功能// 请求者命令调用器管理命令队列批量执行classCommandInvoker{// 命令队列存储所有命令支持批量执行privatefinalListCommandcommandQueuenewArrayList();// 添加命令到队列publicvoidaddCommand(Commandcommand){commandQueue.add(command);}// 执行队列中的所有命令publicvoidexecuteAll(){System.out.println(\n 开始执行命令队列 );for(Commandcommand:commandQueue){command.execute();}System.out.println( 命令队列执行完成 \n);}// 清空队列publicvoidclearQueue(){commandQueue.clear();}}真正执行指令功能的类不修改importjava.util.Date;importjava.util.ArrayList;importjava.util.List;publicclassCommandPattern{publicstaticvoidmain(String[]args){// 1. 创建接收者真正干活的对象RobotrobotnewRobot();WeaponweaponnewWeapon();// 2. 创建请求者命令调用器管理队列CommandInvokerinvokernewCommandInvoker();// 3. 客户端组装命令批量命令变身车辆-延迟3分钟发射5次粒子炮-变身人类-发射3发子弹invoker.addCommand(newTransToCarCommand(robot));// 变身车辆invoker.addCommand(newFireBulletCommand(weapon,3));// 发射3发子弹// 4. 执行所有命令请求者负责执行客户端无需关心细节invoker.executeAll();}}// 两个指令接收者, 真正执行指令对应的功能classRobot{publicvoidtransToCar(){System.out.println([robot] 变身一辆车);}publicvoidtransToHuman(){System.out.println([robot] 变身T800);}}classWeapon{publicvoidfireBullet(){System.out.println([武器] 发射子弹);}publicvoidfireParticleCannon(){System.out.println([武器] 发射粒子炮);}}执行结果: 开始执行命令队列 [robot] 变身一辆车 [日志] 命令变身车辆执行时间Thu Dec 18 14:21:38 CST 2025耗时0ms [武器] 发射子弹 [武器] 发射子弹 [武器] 发射子弹 [日志] 命令发射子弹次数3执行时间Thu Dec 18 14:21:38 CST 2025耗时0ms 命令队列执行完成 命令模式只解决一件事把“要做什么”封装成对象其他能力队列 / 日志 / 撤销都是围绕这个对象自然搭建出来的当看到代码里出现下面的逻辑if (cmd A) doA(); if (cmd B) doB(); 90% 情况该考虑命令模式了