您的位置:首页 > 编程语言 > Java开发

Java 撤销/重做和命令委托

2020-04-30 12:19 896 查看

作为序言,这是我的第一个图书馆,而有点令人尴尬的是我的第一个博客文章😱。任何反馈将不胜感激!所有必须从某个地方开始吗?

当拖延我的学位时,我意识到我的最终项目包含一些有用的命令委托代码,这些代码可以组成一个不错的小图书馆。事不宜迟,让我介绍一下...

试剂名称

对于自述文件(也位于下面)和代码,请检出:

在GitHub上查看

背景

该库起初是另一个项目的撤消/重做控制器,并由我本人和犯罪分子Matt进行了改编,作为我们在GitHub上进行协作的一部分。

该产品必须做三件事:

  • 简化命令委托
  • 简化撤销/重做
  • 尽可能松散耦合

那么,命令委托是什么意思?

假设您有一个打开文件的程序,并为您提供了两个不同的编辑器窗口。每个编辑器窗口显然都有其自己的控制器,但是文件操作很可能在它们之间共享。在我们的案例中,编辑者并不特别在意文件的打开方式,只是不会被遗忘…… 

editor.populate(text)
会很好地完成它们。

FileMenuController
会知道您何时要打开文件,但是我们也希望我们的编辑者也知道,但是我们不一定希望控制器知道编辑器。这是我们的命令委托人进来的地方。

编辑者将订阅命令委托人,说他们想了解某些事件,在这种情况下为

FileOpenCommand
。当文件控制器打开文件时,它将
FileOpenCommand
向委托人发布一个文件,其中包含打开文件所需的任何信息。命令委托者将把此命令转发给编辑器,他们将担心命令的执行。

成功的代表团😄,但我们尚未完成...

撤销重做

正如以前实现过撤消/重做系统的任何人都会知道的那样,最棘手的方面可能是还原状态。为了能够撤消某个动作,您需要以RESTful方式工作的方法(无论状态如何都具有相同的行为),或者您需要存储要返回的状态。

身为宽宏的开发人员,我们决定不在乎,您应该能够做自己想做的事情。是的,自由!因此,撤消/重做过程使用四个实体:委托者、发布者、命令和执行者。命令可能包含状态,也可能不包含状态,但它们始终与执行器紧密耦合。

  • 委托者:手柄执行订阅,并绕过呼吁
    DO
    UNDO
    以及
    REDO
    对命令的执行者
  • 发布者:向委托人发送命令的任何内容
  • 命令:基本上是一个数据包,可能具有执行者要使用的实用方法
  • 执行程序:控制命令的“完成”方式,可以选择执行撤消和重做

那么我该如何安装呢?

只需将其添加为对Maven的依赖!(涵盖了永远出色的Jenkov教程

[code]<span style="color:#f8f8f2"><span style="color:#eff0f9"><code><span style="color:#f9690e"><dependency></span>
<span style="color:#f9690e"><groupId></span>com.logdyn<span style="color:#f9690e"></groupId></span>
<span style="color:#f9690e"><artifactId></span>re-agent<span style="color:#f9690e"></artifactId></span>
<span style="color:#f9690e"><version></span>1.2<span style="color:#f9690e"></version></span>
<span style="color:#f9690e"></dependency></span>
</code></span></span>

那么我该如何使用呢?

我很懒,所以这直接来自自述文件,但是我很想提出改进建议👍

指令

Command
接口的实现 用于触发subscription中的事件
Executor
Command
并未指定执行行为,而是用于触发事件并捕获该事件所需的任何信息。

[code]<span style="color:#f8f8f2"><span style="color:#eff0f9"><code><span style="color:#f39c12">class</span> <span style="color:#7ed07e">ExampleCommand</span> <span style="color:#f39c12">implements</span> <span style="color:#f8f8f2">UndoableCommand</span> <span style="color:#f9690e">{</span>

<span style="color:#7ed07e">@Override</span>
<span style="color:#f39c12">public</span> <span style="color:#f8f8f2">String</span> <span style="color:#7ed07e">getName</span><span style="color:#f9690e">()</span> <span style="color:#f9690e">{</span>
<span style="color:#f39c12">return</span> <span style="color:#f2ca27">"Example Undoable Command"</span><span style="color:#f9690e">;</span>
<span style="color:#f9690e">}</span>
<span style="color:#f9690e">}</span>
</code></span></span>

还有UndoableCommand,它可以被任何执行器执行,尽管如果你想使用undo/redo,必须使用UndoableExecutor。默认情况下,reexecute()方法调用execute(),不过可以覆盖它。UndoableCommand必须提供撤消操作以及初始执行所需的数据。

执行器

Executor
接口的实现用于
Command
在发布a后执行特定行为。

[code]<span style="color:#f8f8f2"><span style="color:#eff0f9"><code><span style="color:#f39c12">class</span> <span style="color:#7ed07e">ExampleExecutor</span> <span style="color:#f39c12">implements</span> <span style="color:#f8f8f2">UndoableExecutor</span><span style="color:#f9690e"><</span><span style="color:#f8f8f2">ExampleCommand</span><span style="color:#f9690e">></span> <span style="color:#f9690e">{</span>
<span style="color:#7ed07e">@Override</span>
<span style="color:#f39c12">public</span> <span style="color:#f39c12">void</span> <span style="color:#7ed07e">execute</span><span style="color:#f9690e">(</span><span style="color:#f8f8f2">ExampleCommand</span> <span style="color:#f8f8f2">command</span><span style="color:#f9690e">)</span> <span style="color:#f9690e">{</span>
<span style="color:#f8f8f2">System</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">out</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">println</span><span style="color:#f9690e">(</span><span style="color:#f2ca27">"Hello, World!"</span><span style="color:#f9690e">);</span>
<span style="color:#f9690e">}</span>

<span style="color:#7ed07e">@Override</span>
<span style="color:#f39c12">public</span> <span style="color:#f39c12">void</span> <span style="color:#7ed07e">unexecute</span><span style="color:#f9690e">(</span><span style="color:#f8f8f2">ExampleCommand</span> <span style="color:#f8f8f2">command</span><span style="color:#f9690e">)</span> <span style="color:#f9690e">{</span>
<span style="color:#f8f8f2">System</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">out</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">println</span><span style="color:#f9690e">(</span><span style="color:#f2ca27">"Goodbye, World!"</span><span style="color:#f9690e">);</span>
<span style="color:#f9690e">}</span>

<span style="color:#7ed07e">@Override</span>
<span style="color:#f39c12">public</span> <span style="color:#f39c12">void</span> <span style="color:#7ed07e">reexecute</span><span style="color:#f9690e">(</span><span style="color:#f8f8f2">ExampleCommand</span> <span style="color:#f8f8f2">command</span><span style="color:#f9690e">)</span> <span style="color:#f9690e">{</span>
<span style="color:#f8f8f2">System</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">out</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">println</span><span style="color:#f9690e">(</span><span style="color:#f2ca27">"Hello again, World!"</span><span style="color:#f9690e">);</span>
<span style="color:#f9690e">}</span>
<span style="color:#f9690e">}</span>
</code></span></span>

订阅命令

订阅a 

Command
要求您指定an 
Executor
Command
它将执行。一个
Executor
将要执行的类型
Command
是订阅,或任何亚类的那个
Command
。结果,仅
Executor
此类型或的子类型之一
Command

[code]<span style="color:#f8f8f2"><span style="color:#eff0f9"><code><span style="color:#f8f8f2">CommandDelegator</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">getINSTANCE</span><span style="color:#f9690e">().</span><span style="color:#7ed07e">subscribe</span><span style="color:#f9690e">(</span><span style="color:#f39c12">new</span> <span style="color:#f8f8f2">ExampleExecutor</span><span style="color:#f9690e">(),</span> <span style="color:#f8f8f2">ExampleCommand</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">class</span><span style="color:#f9690e">);</span>
</code></span></span>

发布(

Doing
)命令

发布a 

Command
就像将其传递给
publish()
方法一样简单。然后将调用
execute()
相关
Executor
类的方法。对的调用
execute()
将与对的调用在同一线程上
publish
,这意味着,如果要启动任务以在后台运行,则必须从后台发布该任务。

如果发布的

Command
内容不可撤消,它将清除当前的撤消历史记录。同样,如果您撤消了a 
Command
并发布了新的a ,则将清除重做历史记录。

[code]<span style="color:#f8f8f2"><span style="color:#eff0f9"><code><span style="color:#f8f8f2">CommandDelegator</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">getINSTANCE</span><span style="color:#f9690e">().</span><span style="color:#7ed07e">publish</span><span style="color:#f9690e">(</span><span style="color:#f39c12">new</span> <span style="color:#f8f8f2">ExampleCommand</span><span style="color:#f9690e">());</span>
</code></span></span>

撤销重做

撤消和重做是上的方法调用

CommandDelegator
。此操作与方法相同
publish()
,将调用相关类的
unexecute()
or 
reexecute()
方法
Executor

[code]<span style="color:#f8f8f2"><span style="color:#eff0f9"><code><span style="color:#f8f8f2">CommandDelegator</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">getINSTANCE</span><span style="color:#f9690e">().</span><span style="color:#7ed07e">undo</span><span style="color:#f9690e">();</span>
<span style="color:#f8f8f2">CommandDelegator</span><span style="color:#f9690e">.</span><span style="color:#7ed07e">getINSTANCE</span><span style="color:#f9690e">().</span><span style="color:#7ed07e">redo</span><span style="color:#f9690e">();</span>
</code></span></span>

全做完了!

原文链接:https://dev.to//jsjlewis96/introducing-re-agent-java-undoredo--command-delegation-56n3

cunxiedian8614 原创文章 0获赞 2访问量 2万+ 关注 私信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: