目录
前言
UML
plantuml
类图
实战代码
模板
Command
Invoker
Receiver
Client
前言
命令模式解耦了命令请求者(Invoker)和命令执行者(receiver),使得 Invoker 不再直接引用 receiver,而是依赖于抽象的命令接口。具体的命令类则直接引用 receiver,通过调用 receiver 的方法来执行命令。
解耦之后,具体命令的增删改不再影响 Invoker,同时,抽象出来的命令请求还能队列化,从而实现撤销和重试功能,或做排列组合合成复杂的命令。
在 Invoker 中,也体现了桥接模式的思想,将命令的抽象和具体的实现分离,使 Invoker 中命令的添加和扩展更加简单。不过具体的命令类并不直接实现处理逻辑,而是交给了 receiver 来实现,这也是命令模式和桥接模式最主要的区别。
UML
plantuml
@startuml 'https://plantuml.com/class-diagraminterface Command {+ execute() : void }class CommandA {- receiver : Receiver+ CommandA(Receiver)+ execute() : void }class CommandB {- receiver : Receiver+ CommandB(Receiver)+ execute() : void }class Receiver {+ executeA() : void+ executeB() : void }class Invoker {- commands : List<Command>+ addCommand(Command) : void+ execute(Command) : void+ executes() : void }class Client {}Command <|.. CommandA Command <|.. CommandBCommandA "1" --> "1" Receiver CommandB "1" --> "1" ReceiverInvoker "1" --> "n" CommandClient ..> Invoker Client ..> Command@enduml
类图
实战代码
模板
Command
public interface Command {void execute();
}public class ConcreteCommand1 implements Command {private Receiver receiver;public ConcreteCommand1(Receiver receiver) {this.receiver = receiver;}public void execute() {receiver.execute1();}
}public class ConcreteCommand2 implements Command {private Receiver receiver;public ConcreteCommand2(Receiver receiver) {this.receiver = receiver;}public void execute() {receiver.execute2();}
}
Invoker
public class Invoker {private List<Command> commands = new ArrayList<Command>();public void addCommand(Command command){commands.add(command);}public void execute(Command command){command.execute();}public void executes(){for(Command command : commands){command.execute();}commands.clear();}
}
Receiver
public class Receiver {public void execute1() {System.out.println("execute1.");}public void execute2() {System.out.println("execute2.");}
}
Client
public class Test {public static void main(String[] args) {Receiver receiver = new Receiver();Invoker invoker = new Invoker();invoker.execute(new Command1(receiver));invoker.addAction(new Command1(receiver));invoker.addAction(new Command2(receiver));invoker.executes();}
}