【设计模式】用Java实现命令模式

一.命令模式介绍与使用场景

命令模式(Command Pattern)是一种行为设计模式,它将请求封装为一个对象,从而使你可以使用不同的请求对客户端进行参数化。命令模式还支持请求的排队、记录日志、撤销操作等功能。

在命令模式中,通常包含以下角色:

  1. 命令接口(Command):定义执行命令的方法,可以是抽象类或接口。
  2. 具体命令类(Concrete Command):实现命令接口,封装了具体的请求和接收者,负责执行请求。
  3. 接收者类(Receiver):执行实际的操作,命令对象将请求委托给接收者来执行。
  4. 调用者类(Invoker):调用命令对象来执行请求,并负责命令的管理和控制。
  5. 客户端(Client):创建具体的命令对象,并将其分配给调用者来执行。

命令模式应用场景:

  1. 当需要将请求发送者和请求接收者解耦时,可以使用命令模式。命令模式通过将请求封装为对象,使得发送者和接收者之间不直接交互,而是通过命令对象进行通信。

  2. 当需要支持请求的排队、记录日志、撤销操作等功能时,命令模式是一个有用的选择。通过将命令对象放入队列或者记录执行日志,可以实现请求的排队和日志记录;同时,可以使用命令对象的撤销方法来实现撤销操作。

  3. 当需要将一组操作作为一个整体来执行时,可以使用命令模式。命令模式将一系列操作封装为一个命令对象,可以通过执行该命令对象来一次性执行一系列操作。

  4. 当希望实现操作的回滚功能时,命令模式可以派上用场。通过在命令对象中添加撤销方法,可以实现对操作的撤销,从而实现回滚功能。

  5. 当需要在不同的上下文中参数化和传递请求时,可以使用命令模式。命令对象可以包含与特定上下文相关的参数,从而在不同的上下文中执行相同的命令。

需要注意的是,命令模式增加了类和对象的数量,可能会带来一定的复杂性。因此,在设计时需要权衡命令的复杂性和可维护性,避免过度使用命令模式。此外,对于简单的操作,直接调用方法可能更加简洁和直观,不一定需要使用命令模式。

二.命令模式实现

首先,我们定义命令接口 Command

public interface Command {
    void execute();
}

然后,我们创建具体命令类 ConcreteCommand

public class ConcreteCommand implements Command {
    private Receiver receiver;
    
    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }
    
    public void execute() {
        receiver.action();
    }
}

 接下来,我们创建接收者类 Receiver,负责执行具体的操作:

public class Receiver {
    public void action() {
        System.out.println("执行具体操作");
    }
}

最后,我们定义调用者类 Invoker,负责管理和控制命令对象:

public class Invoker {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void executeCommand() {
        command.execute();
    }
}

 现在,我们可以在客户端中使用命令模式:

public class Client {
    public static void main(String[] args) {
        Receiver receiver = new Receiver();
        Command command = new ConcreteCommand(receiver);
        
        Invoker invoker = new Invoker();
        invoker.setCommand(command);
        invoker.executeCommand();
    }
}

在上面的示例中,我们创建了一个接收者对象 receiver 和一个具体命令对象 command,将具体命令对象传递给调用者对象 invoker。最后,调用者对象执行命令的 executeCommand() 方法来触发具体命令的执行。 

下面再来举一个在实际应用场景下的例子

假设我们正在开发一个文本编辑器应用程序,我们需要实现一些常见的编辑操作,例如剪切、复制和粘贴。这时,我们可以使用命令模式来封装这些操作,并通过命令对象来执行它们。

首先,我们定义命令接口 Command

public interface Command {
    void execute();
}

然后,我们创建具体命令类 CutCommandCopyCommandPasteCommand

public class CutCommand implements Command {
    private TextEditor editor;
    
    public CutCommand(TextEditor editor) {
        this.editor = editor;
    }
    
    public void execute() {
        editor.cut();
    }
}

public class CopyCommand implements Command {
    private TextEditor editor;
    
    public CopyCommand(TextEditor editor) {
        this.editor = editor;
    }
    
    public void execute() {
        editor.copy();
    }
}

public class PasteCommand implements Command {
    private TextEditor editor;
    
    public PasteCommand(TextEditor editor) {
        this.editor = editor;
    }
    
    public void execute() {
        editor.paste();
    }
}

接下来,我们创建接收者类 TextEditor,它负责执行具体的编辑操作:

public class TextEditor {
    public void cut() {
        System.out.println("执行剪切操作");
    }
    
    public void copy() {
        System.out.println("执行复制操作");
    }
    
    public void paste() {
        System.out.println("执行粘贴操作");
    }
}

最后,我们定义调用者类 Menu,负责管理和控制命令对象:

public class Menu {
    private Command cutCommand;
    private Command copyCommand;
    private Command pasteCommand;
    
    public Menu(Command cutCommand, Command copyCommand, Command pasteCommand) {
        this.cutCommand = cutCommand;
        this.copyCommand = copyCommand;
        this.pasteCommand = pasteCommand;
    }
    
    public void cut() {
        cutCommand.execute();
    }
    
    public void copy() {
        copyCommand.execute();
    }
    
    public void paste() {
        pasteCommand.execute();
    }
}

现在,我们可以在客户端中使用命令模式:

public class Client {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        Command cutCommand = new CutCommand(editor);
        Command copyCommand = new CopyCommand(editor);
        Command pasteCommand = new PasteCommand(editor);
        
        Menu menu = new Menu(cutCommand, copyCommand, pasteCommand);
        menu.cut();
        menu.copy();
        menu.paste();
    }
}

在上面的示例中,我们创建了一个文本编辑器对象 editor,并创建了具体命令对象 cutCommandcopyCommandpasteCommand将它们传递给调用者对象 menu。最后,通过调用调用者对象的方法来执行具体的命令操作。

你可能感兴趣的:(设计模式,设计模式,java,命令模式)