努力理解如何用Java实现命令模式设计

努力理解如何用Java实现命令模式设计,java,command-pattern,Java,Command Pattern,作为项目的一部分,我必须重构一些代码,我想我应该实现一个命令模式设计,但我从多个角度看了它,并不断遇到问题。到目前为止,我只是想从零开始创建一些小东西,但拥有我认为它需要的所有功能 我需要创建一个可以运行编辑器的程序,反复向用户请求命令,解析这些命令并调用相应的函数,直到调用“quit”命令,然后程序退出。需要的一些功能包括:正在工作的“currentImage”(例如命令可能是、open、save、mono等),可以存储已工作图像的“缓存”(我可以在其中“获取”和“放置”图像),将一个图像置于

作为项目的一部分,我必须重构一些代码,我想我应该实现一个命令模式设计,但我从多个角度看了它,并不断遇到问题。到目前为止,我只是想从零开始创建一些小东西,但拥有我认为它需要的所有功能

我需要创建一个可以运行编辑器的程序,反复向用户请求命令,解析这些命令并调用相应的函数,直到调用“quit”命令,然后程序退出。需要的一些功能包括:正在工作的“currentImage”(例如命令可能是、open、save、mono等),可以存储已工作图像的“缓存”(我可以在其中“获取”和“放置”图像),将一个图像置于另一个图像之上的命令,如“上面”

如果我有这样一个编辑器类:

 public class Editor {
      private ArrayList<Image> cache;
      private Image currentImage;

      private Parser parser;

      public Editor(){
           cache = new ArrayList<Image>();
           parser = new Parser();
      }

      public void edit() {
           boolean finished = false;

           while (!finished) {
                command = parser.getCommand();
                finished = command.execute(command.getArgs())
           }
      }

      public boolean aNormalCommand(SomeType args) {
           //Do interesting things with args
           return false;
      }

      public boolean quit(SomeType args) {
           //Check that the args make sense
           return true;
      }

      //
      // more normal functions
      //
 }
public int processCommand(String command) {
    for (Command commandObject : listOfCommands) {
        if (commandObject.isCommand(command)) {
            if (commandObject.processCommand(command)) {
                int response = commandObject.executeCommand();
                return response;
            } else {
                return -1;
            }
        }
    }

    return -2;
}
公共类编辑器{
私有ArrayList缓存;
私人形象;
专用解析器;
公共编辑(){
cache=newarraylist();
parser=newparser();
}
公共作废编辑(){
布尔完成=假;
当(!完成){
command=parser.getCommand();
finished=command.execute(command.getArgs())
}
}
公共布尔命令(SomeType args){
//用args做有趣的事情
返回false;
}
公共布尔退出(SomeType args){
//检查args是否有意义
返回true;
}
//
//更正常的功能
//
}
我一直坚持的事情:

  • 如何实际使其执行所需的命令
  • 如何正确解析输入,以便检查传入有效命令的用户。我已经研究了如何使用枚举和/或哈希映射
  • 如何使添加新功能变得简单
当我考虑将一个命令作为一个接口,即实现execute和undo,然后为获取该对象的每个函数创建类时,我遇到了一个问题:用户想要更改当前图像,这需要额外的东西来切换图像,然后新的对象携带新的对象作为正确的对象

当我考虑如何实现lambdas时,我不确定如何使它在正确的对象上工作。当我查看反射时,不知何故,我的命令需要弄清楚应该对哪个对象进行操作,我不知道解析器如何弄清楚

至于“撤销”,我考虑过使用一个保存过滤器历史记录的ArrayList,撤销操作只会使最后一个成为当前一个(这也解决了拥有不可撤销方法的问题)


希望您能告诉我,我的编辑器类不应该是这样的,一切都会井然有序。

您的编辑器类必须包含执行所需命令所需的字段

所需的一些功能包括:正在使用的“currentImage”(示例命令可能是、open、save、mono等)

编辑器类中有一个当前图像。它可能需要是一个BuffereImage,以便您可以执行某些命令

一个“缓存”,用于存储处理过的图像(我可以在其中“获取”和“放置”图像)

创建缓存的一种方法是创建一个BuffereImage列表

将一个图像置于另一个图像之上的命令,如“over”

现在,BuffereImage必须具有位置信息。您可能需要创建一个子类来保存位置信息和BuffereImage的点或矩形

一旦有了一个包含所有必需字段(包括任何子类)的类,就可以为命令创建一个接口。这里有一个例子

public interface Command {

    public boolean isCommand(String command);
    public boolean processCommand(String command);
    public int executeCommand();

}
isCommand方法标识该命令。“撤消”就是一个例子。对于“Undo”命令字符串,Undo类将返回true

processCommand方法解析该命令。“将图像3移动到位置5”是必须解析的命令示例。如果命令正确解析和验证,则返回true,否则返回false

executeCommand执行该命令。返回一些指示符以指示命令正确执行。我用了一个int。你可以用一个enum

编辑器类将通过构造函数传递给实现该命令接口的具体类

在一个模型类中,创建命令实例列表。然后将实现命令接口的具体类添加到列表中

您可以这样处理命令:

 public class Editor {
      private ArrayList<Image> cache;
      private Image currentImage;

      private Parser parser;

      public Editor(){
           cache = new ArrayList<Image>();
           parser = new Parser();
      }

      public void edit() {
           boolean finished = false;

           while (!finished) {
                command = parser.getCommand();
                finished = command.execute(command.getArgs())
           }
      }

      public boolean aNormalCommand(SomeType args) {
           //Do interesting things with args
           return false;
      }

      public boolean quit(SomeType args) {
           //Check that the args make sense
           return true;
      }

      //
      // more normal functions
      //
 }
public int processCommand(String command) {
    for (Command commandObject : listOfCommands) {
        if (commandObject.isCommand(command)) {
            if (commandObject.processCommand(command)) {
                int response = commandObject.executeCommand();
                return response;
            } else {
                return -1;
            }
        }
    }

    return -2;
}

我不太了解您在表示“更改当前图像”命令的类中看到的问题。你能详细说明一下吗?因为那个类(改变当前图像)需要保存调用该类的对象(编辑器)。可能吗?为什么?如果其他类型的命令不需要保存对其应用的编辑器的引用,为什么一种命令需要保存对该编辑器的引用?我认为您在这里做出了一些非强制性的实现假设。然而,是的,命令对象可以保存对其目标编辑器的引用。如果它的类是
Editor
的内部类,它甚至会自动得到这个结果。我在看buyStock.java和sellStock.java。他们都持有股票。在我的例子中,是编辑器还是图像。它需要在那里执行,我不确定我是否很喜欢这个例子。我也不认为这是一个很好的模拟程序,你正在工作。在任何情况下,尽管您的命令对象确实需要知道要操作的
Editor
,但它们不一定需要它作为成员变量。它可以作为参数提供给他们的
do()
undo()