1、概念
命令模式将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作,属于行为型模式的一种。
2、模式结构
- Command类:是一个抽象类,类中对需要执行的命令进行声明,一般来说要对外公布一个execute方法用来执行命令。
- ConcreteCommand类:Command类的实现类,对抽象类中声明的方法进行实现
- Invoker类:调用者,负责调用命令。
- Receiver类:接收者,负责接收命令并且执行命令
3、使用场景
- 需要将请求调用者和接收者解耦,使得两者不直接交互
- 要在不同的时间指定请求、将请求排队和执行请求
- 需要支持命令的撤销(Undo)操作和恢复(Redo)操作
- 需要将一组操作组合在一起,即支持宏命令
4、优缺点
优点:
- 降低系统的耦合度,使得对象类完全解耦
- 将行为的具体实现封装起来,客户端无需关心行为的具体实现
- 为多种行为提供统一的调用入口,便于程序对行为的管理和控制
- 可以组合成复合命令(宏命令),使操作系统更简单和功能强大
缺点:
- 使用命令模式,不论命令简单还是复杂,都需要写一个命令类来封装,滥用命令模式会导致系统出现过多的具体命令类
5、实例
定义ICommand 类,只有execute方法
public interface ICommand {
void execute();
}
定义MusicPlayer类,负责接收命令并且执行命令
public class MusicPlayer {
public void play() {
}
public void skip() {
}
public void stop() {
}
}
具体命令类PlayCommand
public class PlayCommand implements ICommand {
private MusicPlayer player;
public PlayCommand(MusicPlayer player) {
this.player = player;
}
@Override
public void execute() {
player.play();
}
}
具体命令类SkipCommand
public class SkipCommand implements ICommand {
private MusicPlayer player;
public SkipCommand(MusicPlayer player) {
this.player = player;
}
@Override
public void execute() {
player.skip();
}
}
具体命令类StopCommand
public class StopCommand implements ICommand {
private MusicPlayer player;
public StopCommand(MusicPlayer player) {
this.player = player;
}
@Override
public void execute() {
player.stop();
}
}
定义MusicInvoker 类,负责调用命令
public class MusicInvoker {
private ICommand playCommand;
private ICommand skipCommand;
private ICommand stopCommand;
public void setPlayCommand(ICommand playCommand) {
this.playCommand = playCommand;
}
public void setSkipCommand(ICommand skipCommand) {
this.skipCommand = skipCommand;
}
public void setStopCommand(ICommand stopCommand) {
this.stopCommand = stopCommand;
}
public void play() {
playCommand.execute();
}
public void skip() {
skipCommand.execute();
}
public void stop() {
stopCommand.execute();
}
}
客户端执行实例
public static void main(String[] args) {
// 创建 Receiver(接收者)
MusicPlayer musicPlayer = new MusicPlayer();
// ICommand(抽象命令类)
ICommand playCommand = new PlayCommand(musicPlayer);
ICommand skipCommand = new SkipCommand(musicPlayer);
ICommand stopCommand = new StopCommand(musicPlayer);
// 创建 Invoker(调用者)
MusicInvoker invoker = new MusicInvoker();
invoker.setPlayCommand(playCommand);
invoker.setSkipCommand(skipCommand);
invoker.setStopCommand(stopCommand);
// 测试
invoker.play();
invoker.skip();
invoker.stop();
invoker.play();
invoker.stop();
}
组合命令,形成宏命令,定义IMacroCommand类
public interface IMacroCommand extends ICommand {
void add(ICommand command);
void remove(ICommand command);
}
定义MacroMusicCommand 类
public class MacroMusicCommand implements IMacroCommand {
private static final List<ICommand> commands = new ArrayList<>();
@Override
public void add(ICommand command) {
commands.add(command);
}
@Override
public void remove(ICommand command) {
commands.remove(command);
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void execute() {
commands.forEach(ICommand::execute);
}
}
客户端调用
public static void main(String[] args) {
// 创建 Receiver(接收者)
MusicPlayer musicPlayer = new MusicPlayer();
// ICommand(抽象命令类)
ICommand playCommand = new PlayCommand(musicPlayer);
ICommand skipCommand = new SkipCommand(musicPlayer);
ICommand stopCommand = new StopCommand(musicPlayer);
// 创建 Invoker(调用者)
MacroMusicCommand invoker = new MacroMusicCommand();
invoker.add(playCommand);
invoker.add(skipCommand);
invoker.add(stopCommand);
// 测试
invoker.execute();
}