设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
小米之家的一些家电,用一个app就可以进行控制,每个智能产品只需要提供一个统一的接口给小米app调用就行了,这就用到了命令模式
- 定义
- 通用类图
- 角色
- 场景举例
- 总结
定义
向某些对象发送请求,但不知道请求的接收者是谁,也不知道被请求的操作是哪一个,此时可以采用命令模式
发布者只管发送命令,不管谁去执行。不直接指挥执行者,而是通过命令类去处理
通用类图

角色
Command:命令角色,可以是接口或者抽象类
ConcreateCommand:定义具体命令
Receiver:接收者角色,等待命令并执行
Invoker:调用者,按照客户端指令执行命令,包括撤销命令
命令模式的精髓就是命令者并不需要知道谁去执行这个命令,比如老板让秘书去打印一些文件,命令就是打印文件,秘书在交给具体打印者去打印,老板不关心是小王还是小李打印
场景举例
小王买了两个机器人A,B。A会唱歌,跳舞。B会炒菜。小王可以发布命令“唱歌,跳舞,炒菜”
uml类图设计

抽象类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端就好比遥控器的角色