- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在使用 Java 开发一个小型 UML 编辑器项目,该项目是几个月前开始的。几周后,我得到了一个 UML 类图编辑器的工作副本。
但是现在,我正在完全重新设计它以支持其他类型的图表,例如序列、状态、类等。这是通过实现一个图构建框架来完成的(Cay Horstmann 在这个主题上的工作给了我很大的启发)紫色 UML 编辑器)。
重新设计进行得很顺利,直到我的一位 friend 告诉我,我忘记在项目中添加 Do/Undo 功能,在我看来,这很重要。
想起面向对象的设计类(class),我立刻想到了备忘录和命令模式。
这是交易。我有一个抽象类 AbstractDiagram,它包含两个 ArrayList:一个用于存储节点(在我的项目中称为 Elements),另一个用于存储边(在我的项目中称为 Links)。该图可能会保留一堆可以撤消/重做的命令。很标准。
如何以有效的方式执行这些命令?例如,假设我想移动一个节点(该节点将是一个名为 INode 的接口(interface)类型,并且会有从它派生的具体节点(ClassNode、InterfaceNode、NoteNode 等))。
位置信息作为节点中的一个属性保存,因此通过在节点本身中修改该属性,状态会发生变化。刷新显示时,节点将已移动。这是模式的纪念品部分(我认为),区别在于对象是状态本身。
此外,如果我保留原始节点的克隆(在它移动之前),我可以恢复到它的旧版本。相同的技术适用于节点中包含的信息(类或接口(interface)名称、注释节点的文本、属性名称等)。
问题是,如何在撤消/重做操作时用其克隆替换图中的节点?如果我克隆图表引用的原始对象(在节点列表中),则克隆在图表中不是引用,唯一指向的是命令本身!我是否应该在图中包含根据 ID 查找节点的机制(例如),以便我可以在图中用其克隆替换节点(反之亦然)?是否由 Memento 和 Command 模式来执行此操作?链接呢?它们也应该是可移动的,但我不想为链接创建一个命令(一个只为节点创建一个命令),我应该能够根据命令的对象类型修改正确的列表(节点或链接)是指。
你将如何进行?简而言之,我无法在命令/备忘录模式中表示对象的状态,以便可以有效地恢复它并在图表列表中恢复原始对象,这取决于对象类型(节点或链接)。
非常感谢!
纪尧姆。
PS:如果我不清楚,请告诉我,我会澄清我的信息(一如既往!)。
编辑
这是我的实际解决方案,我在发布此问题之前开始实现。
首先,我有一个 AbstractCommand 类定义如下:
public abstract class AbstractCommand {
public boolean blnComplete;
public void setComplete(boolean complete) {
this.blnComplete = complete;
}
public boolean isComplete() {
return this.blnComplete;
}
public abstract void execute();
public abstract void unexecute();
}
public class MoveCommand extends AbstractCommand {
Moveable movingObject;
Point2D startPos;
Point2D endPos;
public MoveCommand(Point2D start) {
this.startPos = start;
}
public void execute() {
if(this.movingObject != null && this.endPos != null)
this.movingObject.moveTo(this.endPos);
}
public void unexecute() {
if(this.movingObject != null && this.startPos != null)
this.movingObject.moveTo(this.startPos);
}
public void setStart(Point2D start) {
this.startPos = start;
}
public void setEnd(Point2D end) {
this.endPos = end;
}
}
@SuppressWarnings("unused")
private AddRemoveCommand() {}
public AddRemoveCommand(AbstractDiagram diagram, Addable obj, AddRemoveType type) {
this.diagram = diagram;
this.obj = obj;
this.type = type;
}
public void execute() {
if(obj != null && diagram != null) {
switch(type) {
case ADD:
this.obj.addToDiagram(diagram);
break;
case REMOVE:
this.obj.removeFromDiagram(diagram);
break;
}
}
}
public void unexecute() {
if(obj != null && diagram != null) {
switch(type) {
case ADD:
this.obj.removeFromDiagram(diagram);
break;
case REMOVE:
this.obj.addToDiagram(diagram);
break;
}
}
}
最佳答案
我认为你只需要把你的问题分解成更小的问题。
第一个问题:
问:如何用备忘录/命令模式表示您的应用程序中的步骤?
首先,我不知道您的应用程序究竟是如何工作的,但希望您能明白我的意图。假设我想在图表上放置一个具有以下属性的 ClassNode
{ width:100, height:50, position:(10,25), content:"Am I certain?", edge-connections:null}
DiagramController
{
public DiagramController(diagramBuilder:DiagramBuilder)
{
this._diagramBuilder = diagramBuilder;
this._commandStack = new Stack();
}
public void Add(node:ConditionalNode)
{
this._commandStack.push(node);
this._diagramBuilder.Draw(node);
}
public void Undo()
{
var node = this._commandStack.pop();
this._diagramBuilderUndraw(node);
}
}
DiagramController
{
public DiagramController(diagramBuilder:DiagramBuilder)
{
this._diagramBuilder = diagramBuilder;
this._commandStack = new Stack();
}
public void Add(node:ConditionalNode)
{
string graphicalRefId = this._diagramBuilder.Draw(node);
var nodePair = new KeyValuePair<string, ConditionalNode> (graphicalRefId, node);
this._commandStack.push(nodePair);
}
public void Undo()
{
var nodePair = this._commandStack.pop();
this._diagramBuilderUndraw(nodePair.Key);
}
}
关于java - 使用备忘录模式(和命令)存储复杂对象的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/211034/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!