2024年10月命令模式的作用(命令模式的概念)

 更新时间:2024-10-12

  ⑴命令模式的作用(命令模式的概念)

  ⑵本文主要介绍命令模式的功能(命令模式的概念),下面一起看看命令模式的功能(命令模式的概念)相关资讯。

  ⑶目的是将请求转换成一个独立的对象,包含与请求相关的所有信息。这种转换允许你将方法参数化,根据不同的请求延迟请求的执行或者放入队列,并且可以实现撤销操作。

  ⑷动机如果开发一个新的文本编辑器,当前的任务是创建一个有多个按钮的工具栏,让每个按钮对应编辑器的不同操作。创建了一个非常简洁的按钮类,不仅可以用来生成工具栏上的按钮,还可以用来生成各种对话框的通用按钮。尽管所有按钮看起来都相似,但它们可以执行不同的操作(打开、保存、打印和应用等)。).问题是这些按钮的点击处理代码放在哪里?最简单的解决方案是在使用按钮的地方创建大量的子类。这些子类包含了点击按钮后必须执行的代码。

  ⑸但是这种方法有严重的缺陷。首先,创建了大量的子类,每次修改基类按钮,可能都需要修改所有子类的代码。简单来说,GUI代码笨拙地依赖业务逻辑中不稳定的代码(这违反了依赖倒置原则)。更困难的是,复制/粘贴文本等操作可能会在多个地方被调用。例如,用户可以点击小"复制"按钮,或者通过上下文菜单复制一些东西,或者直接使用键盘上的CtrlC。我们的程序本来只有一个工具栏,所以可以用按钮子类来实现各种操作。换句话说,复制按钮子类包含复制文本的代码是可行的。实现了上下文菜单、快捷等功能后,需要将操作码复制到很多类中,或者需要让菜单依赖按钮,这是一个比较差的选择。

  ⑹优秀的软件设计通常封装了更改的部分,这往往会导致软件分层。最常见的例子:第一层负责用户图像界面;另一层负责业务逻辑。GUI层负责在屏幕上呈现漂亮的图形,捕捉所有输入并显示用户和程序的结果。;工作。当有重要的事情需要完成时(比如计算月球轨道或者写年报),GUI层会把工作委托给业务逻辑的底层。在代码中,GUI对象传递一些参数来调用业务逻辑对象。这个过程通常被描述为一个对象向另一个对象发送请求。

  ⑺命令模式建议GUI对象不要直接提交这些请求。请求的所有细节(如被调用对象、方法名和参数列表)都要提取出来,形成一个命令类,这个命令类只包含一个触发请求的方法。GUI对象可以触发命令,命令对象将自己处理所有细节。所有命令都实现相同的接口。界面通常只有一个不带任何参数的执行方法,它允许您使用同一个请求发送方执行不同的命令,而无需与特定的命令类耦合。此外,还有一个额外的好处。现在你可以在运行时切换连接到发送器的命令对象,从而改变发送器的行为。

  ⑻适用性如果需要通过一个操作来参数化一个对象,可以使用mandmode命令模式将一个特定的方法调用转换成一个独立的对象。因此,您可以将命令作为方法的参数传递,将命令保存在其他对象中,或者在运行时切换连接的命令。

  ⑼如果要将操作放入队列或远程执行操作,可以使用命令模式。像其他对象一样,命令也可以序列化(序列化意味着转换为字符串),这样就可以很容易地将它们写入文件或数据库。一段时间后,字符串可以恢复到原来的命令对象。因此,您可以延迟或计划命令的执行。但是它的作用远不止于此!同样,你也可以将命令放入队列,记录下来或者通过网络发送。

  ⑽如果要实现操作回滚功能,可以使用命令模式。虽然有很多方法可以实现撤销和重做功能,但命令模式可能是最常用的一种。为了能够回滚操作,需要实现已执行操作的历史功能。命令历史是一个堆栈结构,包含所有已执行的命令对象及其相关的程序状态备份。这种方法有两个缺点:

  ⑾首先,保存程序状态的功能不容易实现,因为有些状态可能是私有的。您可以使用memento模式在一定程度上解决这个问题。

  ⑿其次,备份状态可能会占用大量内存。因此,有时需要求助于另一种实现方法:命令不需要恢复原始状态,而是执行相反的操作。逆向操作也有代价:可能很难甚至不可能实现。

  ⒀支持修改日志,这样当系统崩溃时,可以重做修改。在命令界面中增加加载操作和存储操作可以用来保持一致的修改日志。从崩溃中恢复的过程包括从磁盘重新读取记录的命令,并使用执行操作重新执行它们,以构建具有基于原语操作的高级操作的系统。这种结构在支持事物的信息系统中很常见。事务封装了一组对数据的更改。命令模式提供了一种对事务建模的方法。命令有一个公共接口,使您能够以相同的调用所有事务。同时,很容易添加新的事务来扩展系统的结构。

  ⒁效果。命令模式将调用操作的对象与知道如何实现操作的对象分离开来(单一责任原则)。

  ⒂实现撤销和恢复功能。

  ⒃多个命令可以组合成一个组合命令。普通的一般来说,组合命令是复合模式的一个例子。

  ⒄您可以在程序中创建新命令,而无需修改客户端代码(开闭原则)

  ⒅代码实现mands/mand.java:;抽象基本命令。

  ⒆包mand.mands导入命令.编辑器.编辑器;/****作者高明*date//-:*/public抽象类命令{publicEditoreditor私有字符串备份;mand(EditorEditor){this.Editor=Editor;}voidbackup{backup=editor.textfield.gettext;}publicvoidundo{editor.textfield.settext(backup);}公共抽象布尔execute;}mands/Copymand.java:将选定的文本复制到剪贴板。

  ⒇包mand.mands导入命令.编辑器.编辑器;/****作者高明*date//-:*/publilasscopymand扩展命令{publiopymand(EditorEditor){super(Editor);}Overridepublicbooleanexecute{editor.clipboard=editor.textfield.getselectedtext;返回false}}mands/Pastemand.java:从剪贴板粘贴文本。

  ⒈包mand.mands导入命令.编辑器.编辑器;/****作者高明*date//-:*/publilasspastemand扩展命令{publicpastemand(EditorEditor){super(Editor);}Overridepublicbooleanexecute{if(editor.clipboard==null||editor.clipboard.isempty)返回falsebackup;editor.textfield.insert(editor.clipboard,editor.textfield.getcaretposition);返回true}}mands/Cutmand.java:将文本剪切到剪贴板。

  ⒉包mand.mands导入命令.编辑器.编辑器;/****作者高明*date//-:*/publilasscutmand扩展命令{publiutmand(EditorEditor){super(Editor);}Overridepublicbooleanexecute{if(editor.textfield.getselectedtext。isEmpty)返回falsebackup;stringsource=editor.textfield.gettext;editor.clipboard=editor.textfield.getselectedtext;editor.textfield.settext(cutstring(source));返回true}私有字符串cutString(Stringsource){Stringstart=source.substring(,editor.textfield.getselectionstart);stringend=source.substring(editor.textfield.getselectionend);返回起始端;}}mands/mandHistory.java:指挥史

  ⒊包mand.mands导入Java.util.stack;/****作者高明*date//-:*/publilassmandhistory{privateStackmandhistory=newStack;publicvoidpush(mandc){history.push(c);}公共命令pop{returnhistory.pop;}publicbool:文本编辑器的GUI。

  ⒋packagemand.editor导入mand.mands.*;导入javax.swing.*;导入Java.awt.*;导入Java.awt.event.actionevent;导入Java.awt.event.actionlistener;/****作者高明*date//-:*/publilassEditor{publicJTextAreatextField;公共字符串剪贴板;私有mandhistoryhistory=newmandhistory;publicvoidinit{JFrameframe=newJFrame("文本编辑器(类型使用按钮,卢克!)");JPanelcontent=newJPanel;兄弟me.setContentPane(内容);frame.setdefaultcloseoperation(windowconstants。EXIT_ON_CLOSE);content.setLayout(新的BoxLayout(content,BoxLayout。y_轴));textField=newJTextArea;textfield.setlinewrap(true);content.add(textField);JPanelbuttons=newJPanel(newflowlayout(flowlayout。居中));JButtonctrlc=newJButton("CtrlC");JButtonctrlx=newJButton("CtrlX");JButtonctrlLV=newJButton("CtrlV");JButtonctrlZ=newJButton("CtrlZ");编辑器editor=thisctrlc.addactionlistener(newactionlistener{Overridepublicvoidactionperformed(ActionEvente){executemand(newcopymand(editor));}});ctrlx.addactionlistener(newactionlistener{Overridepublicvoidactionperformed(actionevente){executemand(newcutmand(editor));}});ctrlv.addactionlistener(newactionlistener{Overridepublicvoidactionperformed(actionevente){executemand(newpastemand(editor));}});ctrlz.addactionlistener(newactionlistener{OverridepublicvoidactionPerformed(actionevente){undo;}});buttons.add(ctrlLC);buttons.add(ctrlLX);buttons.add(ctrlLV);buttons.add(ctrlZ);content.add(按钮);frame.setSize(,);frame.setlocationrelativeto(null);frame.setvisible(true);}privatevoidexecutemand(mand命令){if(mand.execute){history.push(mand);}}私有voidundo{if(history.isempty)return;mandmand=history.pop;如果(命令!=null){mand.undo;}}}D:客户端代码

  ⒌包命令;导入命令.编辑器.编辑器;/****作者高明*date//-:*/publilassDemo{publicstaticvoidmain(String[]args){EditorEditor=newEditor;editor.init;}}运行结果

  ⒍与其他模式的关系责任链模式、命令模式、中介者模式和观察者模式用于处理请求的发送者和接收者之间的不同连接模式:-责任链动态地将请求按顺序传输给一系列潜在接收者,直到其中一个接收者处理该请求-命令在发送者和请求者之间建立单向连接-中介者清除发送者和请求者之间的直接连接,并强制它们通过中间对象间接通信-观察者允许接收者动态地订阅或取消接收请求。

  ⒎你可以同时使用命令和纪念品模式来实现"撤消"。在这种情况下,命令用于在目标对象上执行各种操作,备忘录用于在命令执行之前保存对象的状态。原型模式可用于保存命令的历史。访问者模式可以被视为命令模式的增强版本对象可以对不同类的各种对象执行操作。命令和策略模式看起来很相似,因为两者都可以通过某些行为来参数化对象。然而,他们的意图是非常不同的:-您可以使用命令将任何操作转换为对象。操作的参数将成为对象的成员变量。您可以延迟操作的执行,将操作放入队列,保存历史命令或将命令发送到远程服务,等等。-策略通常可以用来描述完成某件事情的不同,允许你在同一个上下文类中切换算法。

  ⒏责任链的管理者可以用命令来实现。在这种情况下,您可以对请求所表示的同一个上下文对象执行许多不同的操作。还有一种实现,就是请求本身就是一个命令对象。在这种情况下,您可以在由一系列不同上下文连接的链上执行相同的操作。

  ⒐已知应用的例子:命令模式在Java代码中非常常见。在大多数情况下,它被用来代替包含行为的回调函数。此外,它还用于任务排序和记录操作历史等。下面是核心Java库中的一些例子:java.lang.Runnable的所有实现javax.swing.Action的所有实现标识方法:一个命令模式可以由一个抽象或接口类型(sender)中的行为方法标识,该方法调用另一个不同的抽象或接口类型(receiver)实现中的方法,该方法在创建时被命令模式的实现封装。

您可能感兴趣的文章:

相关文章