在ArrayLists中使用Command模式进行撤消和重做

时间:2015-04-15 20:41:41

标签: java arraylist command-pattern

所以我有一个程序,您可以登录并在friends arraylist中添加/删除朋友。此外,我可以喜欢某件事,那件事将被存储到likes arraylist中。我被要求为我做的任何动作制作撤销和重做选项。

所以我想添加 apple 作为朋友。之后当我选择撤消选项时,我可以撤消该操作,因此 apple 不会是我的朋友。当输入是我输入存储到Command Pattern arraylist中的任何名称或单词时,如何使用friends来处理此问题?

我做了一些研究,发现使用命令模式可能是我最好的选择,因为这必须在我已经拥有的Facebook类别下完成。我假设我将不得不使用两个不同的堆栈,但我在主题中有点迷失。

我决定添加我所拥有的部分内容,这样我就可以获得更多帮助,了解我需要做什么以及我的程序是做什么的。

在驱动程序中

Facebook facebook1 = new Facebook();

            if (userInput == 6) 
            {
                System.out.println("Login");
                String operand1 = getOperand("What is the Username? ");
                String operand2 = getOperand("What is the Password? ");
                System.out.println("Enter a friend to be added. ");
                String operand3 = getOperand("What is the Username? ");
                facebook1.friend(operand3);
            }

            if (userInput == 7) 
            {
                System.out.println("Login");
                String operand1 = getOperand("What is the Username? ");
                String operand2 = getOperand("What is the Password? ");
                System.out.println("Enter a friend to be removed. ");
                String operand3 = getOperand("What is the Username? ");
                facebook1.defriend(operand3);
            }
            if (userInput == 12) 
            {
                System.out.println("Login");
                String operand1 = getOperand("What is the Password? ");
                facebook1.undo();
            }

            if (userInput == 13) 
            {
                System.out.println("Login");
                String operand1 = getOperand("What is the Password? ");
                facebook1.redo();
            }

在Facebook班级

ArrayList<FacebookUser> recommendedFriends = new ArrayList<FacebookUser>();

void friend(String newFriend)
    {
        boolean positiveChecker = false;

        for (int i = 0; i < recommendedFriends.size(); i++) 
        {

            if (recommendedFriends.get(i).toString().equalsIgnoreCase(newFriend)) 
            {
                System.out.println("Error: This friend already exists.");
                positiveChecker = true;
            }

        }
        if (positiveChecker == false) 
        {
            FacebookUser friend = new FacebookUser(newFriend, newFriend );
            recommendedFriends.add(friend);
            System.out.println(friend + " is now your friend.");
        }
        positiveChecker = false;
    }

     void defriend(String formerFriend)
    {
         boolean positiveChecker = false;

            for (int i = 0; i < recommendedFriends.size(); i++) 
            {

                if (recommendedFriends.get(i).toString().equalsIgnoreCase(formerFriend)) 
                {
                    recommendedFriends.remove(i);
                    System.out.println(formerFriend + " has been removed from your friends list.");
                    positiveChecker = true;
                }
                if (recommendedFriends.size() == (i + 1) && recommendedFriends.get(i).toString() != formerFriend
                        && positiveChecker == false) 
                {
                    System.out.println("Error: There is no friend with this username.");

                }

            }
            positiveChecker = false;
    }

public interface Command 
    {
        public void undo();
        public void redo();
    }

2 个答案:

答案 0 :(得分:3)

当你撤消2件事然后做一个全新的动作时,你需要忘记&#34; &#34;重做历史&#34;并用新命令替换它,对吧?

例如......

  1. 添加朋友吉姆
  2. 添加好友账单
  3. 添加朋友吉尔
  4. 删除吉姆
  5. 撤消
  6. 撤消
  7. 国家应该是&#34; Jim&#34;和&#34;比尔&#34;。

    所以你只需要一个列表和一个指向当前&#34;命令&#34;的指针,例如......

    // Note: NOT thread safe!
    public class CommandStack {
        private List<Command> commands = Collections.emptyList();
        private int nextPointer = 0;
    
        public void doCommand(Command command) {
            List<Command> newList = new ArrayList<>(nextPointer + 1)
    
            for(int k = 0; k < nextPointer; k++) {
                newList.add(commands.get(k));
            }
    
            newList.add(command);
    
            commands = newList;
            nextPointer++;
    
            // Do the command here, or return it to whatever called this to be done, or maybe it has already been done by now or something
            // (I can only guess on what your code currently looks like...)
            command.execute();
        }
    
        public boolean canUndo() {
            return nextPointer > 0;
        }
    
        public void undo() {
            if(canUndo()) {
                nextPointer--;
                Command commandToUndo = commands.get(nextPointer);
                // Undo the command, or return it to whatever called this to be undone, or something
                command.undo();
             } else {
                 throw new IllegalStateExcpetion("Cannot undo");
             }
        }
    
        public boolean canRedo() {
            return nextPointer < commands.size();
        }
    
        public void redo() {
            if(canRedo()) {
                commandToDo = commands.get(nextPointer);
                nextPointer++;
                // Do the command, or return it to whatever called this to be re-done, or something
                commandToDo.execute();
            } else {
                throw new IllegalStateException("Cannot redo");
            }
        }
    }
    

    如果我有......

    interface Command { /* execute / undo etc */ }
    
    public class AddFriendCommand implements Command {
        private String friendName;
    
        // ... other fields, constructor / getters etc ...
    
        public void execute() {
            // Actually do it...
            System.out.println("Added friend " + name);
        }
    
        public void undo() {
            // Undo it...
            System.out.println("Removed friend " + name);
        }
    }
    
    public class RemoveFriendCommand implements Command {
        private String friendName;
    
        // ... other fields, constructor / getters etc ...
    
        public void execute() {
            // Actually do it, maybe throw exception if friend does not exist?
            // (that would have to be a runtime exception unless you want the interface's method to throw stuff);
            System.out.println("Removed friend " + name);
        }
    
        public void undo() {
            // Undo it...
            System.out.println("Added friend " + name);
        }
    }
    

    您可以使用...重复上述序列。

    CommandStack stack = new CommandStack();
    
    stack.doCommand(new AddFriendCommand("Jim"));
    stack.doCommand(new AddFriendCommand("Bill"));
    stack.doCommand(new AddFriendCommand("Jill"));
    stack.doCommand(new RemoveFreindCommand("Jim"));
    
    stack.undo();
    stack.undo();
    

    如果你现在做了一个新的命令(通过doCommand),你会忘记你曾经添加过&#34; Jill&#34;或删除&#34; Jim&#34;,而是现在记住新命令和未撤消的命令历史记录的其余部分。

    希望这有帮助。

答案 1 :(得分:0)

您误解了命令模式的工作原理。您希望单独List Commands,其中每个Command实例代表操作

所以你想要有类似的东西:

List<Command> actionStack;

然后有像

这样的东西
public class AddCommand implements Command {
    private final void List<FacebookUser> userList;
    private final void FacebookUser newUser;

    public AddCommand(List<FacebookUser> userList, FacebookUser newUser) {
        this.userList = userList;
        this.newUser = newUser;
    }

    @Override
    public void undo() {
        userList.remove(newUser);
    }

    @Override
    public void redo() {
        userList.add(newUser);
    }
}