设计模式之行为型模式(二)命令模式

67 阅读3分钟

1.职责链模式 2.命令模式 3.迭代器模式 4.观察者模式 5.策略模式 6.模板方法模式 7.访问者模式 8.中介者模式 9.备忘录模式 10.状态模式

由于学习难度较大或相对用途较少 本章不会讲解7-10四种设计模式

接下来针对以上6种设计模式进行单独讲解

2 命令模式

2.1 定义

将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化。

命令模式将请求的发送者和处理者完全解耦,发送者和处理者之间没有直接的引用关系,发送请求的对象只知道怎么发送请求,而不必知道请求如何被处理。

举例说明:开关会下达开或者关的命令,命令通过电线传播,至于电线连接时灯泡还是风扇,开关完全不知情。

再比如:一般OA系统都会有快捷键指令,自己可以设置某个快捷键具体执行某些能力,用户点击快捷键向系统发送指令,这时候快捷键只是一个命令,具体要执行哪个能力由后台设置的对应关系决定。如下图,设置好功能键代表的功能之后,按下功能键1,这时候只是给系统发送了一个功能键1的命令,但是具体执行打开帮助文档还是最小化到托盘或者是自动截屏,是由后台系统决定,而不是由这个功能键决定。

image.png

2.2 UML图

image.png

从上面UML图中可以看出

Command为抽象命令类,一般是一个抽象类或接口,在其中声明了用于执行请求的execute()等方法,通过这些方法可以调用请求接收者的相关操作。

ConcreteCommand为具体命令类,实现了在抽象命令类中声明的方法,将接收者对象的动作绑定其中。在实现execute()方法时,将调用接收者对象的相关操作(Action)。

Invoker为调用者,即请求发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的execute()方法,从而实现间接调用请求接收者的相关操作。

Receiver为接收者:接收者执行与请求相关的操作,它具体实现对请求的业务处理。

2.3 代码实现

// 抽象命令类  
public interface Command {  
    void execute();  
}  
  
// 具体命令类A  
public class ConcreteCommandA implements Command {  
    private Receiver receiver;  
  
    public ConcreteCommandA(Receiver receiver) {  
        this.receiver = receiver;  
    }  
  
    @Override  
    public void execute() {  
        receiver.action();  
    }  
}  
  
// 具体命令类B  
public class ConcreteCommandB implements Command {  
    private Receiver receiver;  
  
    public ConcreteCommandB(Receiver receiver) {  
        this.receiver = receiver;  
    }  
  
    @Override  
    public void execute() {  
        receiver.action();  
    }  
}  
  
// 接收者类  
public class Receiver {  
    public void action() {  
        System.out.println("Receiver action");  
    }  
}  
  
// 调用者类  
public class Invoker {  
    private Command command;  
  
    public Invoker(Command command) {  
        this.command = command;  
    }  
  
    public void setCommand(Command command) {  
        this.command = command;  
    }  
  
    public void executeCommand() {  
        command.execute();  
    }  
}

public class Main {  
    public static void main(String[] args) {  
        // 创建接收者对象  
        Receiver receiver = new Receiver();  
        // 创建具体命令对象A,将接收者对象传入构造函数中,绑定动作关系
        ConcreteCommandA commandA = new ConcreteCommandA(receiver);  
        // 创建具体命令对象B,将接收者对象传入构造函数中,绑定动作关系  
        ConcreteCommandB commandB = new ConcreteCommandB(receiver);  
         // 创建调用者对象,将具体命令对象A传入构造函数中,绑定关系
        Invoker invokerA = new Invoker(commandA);    
        Invoker invokerB = new Invoker(commandB);
         // 调用调用者的executeCommand方法,间接调用接收者的相关操作
        invokerA.executeCommand();  
        invokerB.executeCommand();

2.4 拓展

宏命令模式是命令模式+组合模式的实现,其UML图如下所示

image.png 其中MarcoCommand充当组合模式中的容器节点,具体command类充当叶子节点,再MarcoCommand中递归调用其子节点。

具体组合模式代码可参考设计模式之结构型模式(三)组合模式 - 掘金 (juejin.cn)本篇文章