命令模式
-
定义:命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
-
优点: 1)将发起请求的对象与执行请求的对象解耦。发起请求的对象是调用者,调用者只要调用命令对象的execute()方法就可以让接收者工作,而不必知道具体的接收者对象是谁、是如何实现的,命令对象会负责让接收者执行请求的动作,命令对象起到了纽带桥梁的作用。2) 容易设计一个命令队列。只要把命令对象放到列队,就可以多线程的执行命令。3) 容易实现对请求的撤销和重做。
-
缺点:可能导致某些系统有过多的具体命令类,增加了系统的复杂度。
-
博客:https://segmentfault.com/a/1190000012203360
-
实例:以MusicPlayer(音乐播放器)为案例,播放器有播放(play),跳过(skip),停止(stop)等功能,是一种比较典型的命令模式。
-
类图:
-
代码:
/**
* 命令接口类
*/
public interface Command {
/**
* 执行命令
*/
void execute();
}
/**
* 命令实现类:播放
*/
public class PlayCommand implements Command {
/**
* 接收者
*/
private MusicPlayer musicPlayer;
public PlayCommand(MusicPlayer musicPlayer) {
this.musicPlayer = musicPlayer;
}
@Override
public void execute() {
musicPlayer.play();
}
}
/**
* 命令实现类:跳过
*/
public class SkipCommand implements Command {
/**
* 接收者
*/
private MusicPlayer musicPlayer;
public SkipCommand(MusicPlayer musicPlayer) {
this.musicPlayer = musicPlayer;
}
@Override
public void execute() {
musicPlayer.skip();
}
}
/**
* 命令实现类:暂停
*/
public class StopCommand implements Command {
/**
* 接收者
*/
private MusicPlayer musicPlayer;
public StopCommand(MusicPlayer musicPlayer) {
this.musicPlayer = musicPlayer;
}
@Override
public void execute() {
musicPlayer.stop();
}
}
/**
* 请求者角色,接收客户端发送过来的指令
*/
public class MusicInvoker {
private Command playCommand;
private Command skipCommand;
private Command stopCommand;
public void setPlayCommand(Command playCommand) {
this.playCommand = playCommand;
}
public void setSkipCommand(Command skipCommand) {
this.skipCommand = skipCommand;
}
public void setStopCommand(Command stopCommand) {
this.stopCommand = stopCommand;
}
public void play() {
playCommand.execute();
}
public void skip() {
skipCommand.execute();
}
public void stop() {
stopCommand.execute();
}
}
/**
* 测试命令模式
*/
public class TestCommand {
public static void main(String[] args) {
// 创建 接收者
MusicPlayer musicPlayer = new MusicPlayer();
// 创建命令
Command playCommand = new PlayCommand(musicPlayer);
Command skipCommand = new SkipCommand(musicPlayer);
Command stopCommand = new StopCommand(musicPlayer);
// 创建命令请求者
MusicInvoker invoker = new MusicInvoker();
invoker.setPlayCommand(playCommand);
invoker.setSkipCommand(skipCommand);
invoker.setStopCommand(stopCommand);
// 测试
invoker.play();
invoker.skip();
invoker.stop();
invoker.play();
invoker.stop();
}
}