设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)

小米之家的一些家电,用一个app就可以进行控制,每个智能产品只需要提供一个统一的接口给小米app调用就行了,这就用到了命令模式

  1. 定义
  2. 通用类图
  3. 角色
  4. 场景举例
  5. 总结

定义

向某些对象发送请求,但不知道请求的接收者是谁,也不知道被请求的操作是哪一个,此时可以采用命令模式

发布者只管发送命令,不管谁去执行。不直接指挥执行者,而是通过命令类去处理

通用类图

img

角色

Command:命令角色,可以是接口或者抽象类

ConcreateCommand:定义具体命令

Receiver:接收者角色,等待命令并执行

Invoker:调用者,按照客户端指令执行命令,包括撤销命令

命令模式的精髓就是命令者并不需要知道谁去执行这个命令,比如老板让秘书去打印一些文件,命令就是打印文件,秘书在交给具体打印者去打印,老板不关心是小王还是小李打印

场景举例

小王买了两个机器人A,B。A会唱歌,跳舞。B会炒菜。小王可以发布命令“唱歌,跳舞,炒菜”

uml类图设计

img

抽象类Command

1
2
3
public interface Command {
void execute();
}

AB机器人(Receiver角色)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ARobot {
void sing() {
System.out.println("A机器人在唱歌");
}

void dance() {
System.out.println("A机器人在跳舞");
}
}
public class BRobot {
void makeFry() {
System.out.println("B机器人在炒菜");
}
}

具体命令(ConcreateCommand角色)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class SingCommand implements Command {
private ARobotReceiver receiver;

public SingCommand(ARobotReceiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.sing();
}
}
public class DanceCommand implements Command{
private ARobotReceiver receiver;

public DanceCommand(ARobotReceiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.dance();
}
}
public class MakeFryCommand implements Command{
private BRobotReceiver receiver;

public MakeFryCommand(BRobotReceiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.makeFry();
}
}

调用者(Invoker角色)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class RobotInvoker implements Command{
private final List<Command> commands = new ArrayList<>();

public void addCommand(Command command) {
commands.add(command);
}

@Override
public void execute() {
for (Command c : commands) {
c.execute();
}
}
}

client测试

1
2
3
4
5
6
7
8
//创建王老板
RobotInvoker wang = new RobotInvoker();
//命令初始化
wang.addCommand(new SingCommand());
wang.addCommand(new DanceCommand());
wang.addCommand(new MakeFryCommand());
//执行命令
wang.execute();

总结

  • 源码实际应用场景还没找到,后续找到补充
  • 命令接口除了可以执行操作,也可以进行撤销(关联别的设计模式,后续补充)
  • 一个命令类只能完成一个命令比如上面的SingCommand/DanceCommand/MakeFryCommand
  • 调用者Invoker只知道命令接口,并不知道具体命令。就好比遥控器只知道哪个能换台,哪个能调节音量,不管它怎么实现的。
  • client端就好比遥控器的角色