设计模式之命令模式

什么是命令模式

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作。

还是通过例子来理解这种设计模式。

举个栗子

命令模式的模型图

命令模式有三种角色:接收者、命令、调用者,他的封装性特别好,下面来体验一下编码过程

  • 抽象接收者及实现
1
2
3
4
5
6
7
8
9
public abstract class Receiver {
public abstract void action();
}
public class ConcreteReceiver extends Receiver {
@Override
public void action() {
//接收者任务
}
}
  • 抽象命令及实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public abstract class Command {
public abstract void execute();
}

public class ConcreteCommand extends Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
//执行命令
receiver.action();
}
}
  • 调用者
1
2
3
4
5
6
7
8
9
10
public class Invoker {
//接受并执行
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void invokeCommand(){
command.execute();
}
}
  • 使用场景
1
2
3
4
5
6
7
8
9
public class Client {
public static void main(String[] args) {
Invoker invoker=new Invoker();
Receiver receiver=new ConcreteReceiver();
Command command=new ConcreteCommand(receiver);
invoker.setCommand(command);
invoker.invokeCommand();
}
}

这就是命令模式,它的特点是命令的接收者和调用者之间没有任何耦合,这样可以很容易地应对各种变化。

适用范围

命令模式的使用和它的名字一样,只要是命令的地方就可以用命令模式,结合其他设计模式使用会更加能发挥它的价值。

优点缺点

优点就是命令的接受和调用完全解耦,有利于扩展,而且开发简单。

缺点就是命令过多的时候类的数量会增加,如果不结合其他设计模式难以维护。

封闭接收者的命令模式

在命令模式中,其实有时候调用者无需知道命令的接收者,此时可以换一种方式,变更代码如下

  • 抽象命令及实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class Command {
protected final Receiver receiver;
public Command(Receiver receiver) {
this.receiver = receiver;
}
public abstract void execute();
}
public class ConcreteCommand extends Command {
//默认接收者
public ConcreteCommand() {
super(new ConcreteReceiver());
}
//自定义接收者
public ConcreteCommand(Receiver receiver) {
super(receiver);
}
@Override
public void execute() {
//执行命令
receiver.action();
}
}
  • 调用场景
1
2
3
4
5
6
7
8
public class Client {
public static void main(String[] args) {
Invoker invoker=new Invoker();
Command command=new ConcreteCommand();
invoker.setCommand(command);
invoker.invokeCommand();
}
}

这样高层模块就无需知道具体接收者是谁了,这也是命令模式的一种很常用的用法。

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!