命令模式介绍
命令模式(Command Pattern),是行为模式之一。命令模式相对于其他设计模式,没有严格的条框,从而显得灵活多变。在实际生活中,我们碰到很多命令模式,比如手机的中有菜单命令,在点击“关机”命令后,系统会执行一系列的操作,如暂停处理的操作,保存相应的系统设置,关闭掉打开的程序等。对于这一系列的操作,用户不用管,系统会自动执行。命令模式就是如此一辙,将一系列的方法调用封装,用户只需要调用一个方法执行,那么所有这些封装的方法就会挨个执行调用。命令模式的定义
将一个请求封装成一个对象,从而让用户使用不同的请求客户端参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
命令模式的使用场景
需要抽象出待执行的动作,然后以参数的形式提供出来--类似于过程涉及中的回调机制,而命令模式正是回调机制的一个面向对象的替代品。在不同的时刻指定、排列和执行请求,一个命令对象可以有与初始请求无关的生存期。
需要支持取消操作。
支持修改日志功能,这样当系统崩溃时,这些修改可以被重做一遍。
需要支持事务操作。
命令模式的UML类图
具体实现
创建接受者角色
public class Music {
/**
* 真正的逻辑操作 - 播放
*/
public void play() {
System.out.println("play");
}
/**
* 真正的逻辑操作 - 暂停
*/
public void pause() {
System.out.println("pause");
}
/**
* 真正的逻辑操作 - 下一首
*/
public void next() {
System.out.println("next");
}
/**
* 真正的逻辑操作 - 上一首
*/
public void previous() {
System.out.println("previous");
}
}
创建命令角色
public interface Command {
/**
* 命令执行方法
*/
void execute();
}
创建具体命令角色
/**
* 播放命令类
* @Author teaphy
* @Date 2016/8/18
*/
public class PlayCommand implements Command {
// 持有音乐播放器的对象
private Music mMusic;
public PlayCommand(Music music) {
this.mMusic = music;
}
/**
* 命令执行方法
*/
public void execute() {
// 调用音乐播放器的具体操作 - 播放
mMusic.play();
}
}
/**
* 暂停命令类
* @Author teaphy
* @Date 2016/8/18
*/
public class PauseCommand implements Command {
// 持有音乐播放器的对象
private Music mMusic;
public PauseCommand(Music music) {
this.mMusic = music;
}
/**
* 命令执行方法
*/
public void execute() {
// 调用音乐播放器的具体操作 - 暂停
mMusic.pause();
}
}
/**
* 下一首命令类
* @Author teaphy
* @Date 2016/8/18
*/
public class NextCommand implements Command {
// 持有音乐播放器的对象
private Music mMusic;
public NextCommand(Music music) {
this.mMusic = music;
}
/**
* 命令执行方法
*/
public void execute() {
// 调用音乐播放器的具体操作 - 下一首
mMusic.next();
}
}
/**
* 上一首命令类
* @Author teaphy
* @Date 2016/8/18
*/
public class PreviousCommand implements Command {
// 持有音乐播放器的对象
private Music mMusic;
public PreviousCommand(Music music) {
this.mMusic = music;
}
/**
* 命令执行方法
*/
public void execute() {
// 调用音乐播放器的具体操作 - 上一首
mMusic.previous();
}
}
创建请求者角色
/**
* 请求者角色
* @Author teaphy
* @Date 2016/8/18
*/
public class Invoker {
PlayCommand playCommand;
PauseCommand pauseCommand;
NextCommand nextCommand;
PreviousCommand previousCommand;
/**
* 操作 - 暂停
*/
public void play() {
pauseCommand.execute();
}
/**
* 操作 - 暂停
*/
public void pause() {
pauseCommand.execute();
}
/**
* 操作 - 下一首
*/
public void next() {
nextCommand.execute();
}
/**
* 操作 - 上一首
*/
public void previous() {
previousCommand.execute();
}
public PlayCommand getPlayCommand() {
return playCommand;
}
public void setPlayCommand(PlayCommand playCommand) {
this.playCommand = playCommand;
}
public PauseCommand getPauseCommand() {
return pauseCommand;
}
public void setPauseCommand(PauseCommand pauseCommand) {
this.pauseCommand = pauseCommand;
}
public NextCommand getNextCommand() {
return nextCommand;
}
public void setNextCommand(NextCommand nextCommand) {
this.nextCommand = nextCommand;
}
public PreviousCommand getPreviousCommand() {
return previousCommand;
}
public void setPreviousCommand(PreviousCommand previousCommand) {
this.previousCommand = previousCommand;
}
}</span>
创建操作者角色
<span style="font-size:14px;">public class Listener {
public static void main(String[] args) {
// 创建音乐播放器对象
Music music = new Music();
// 创建执行不同的命令
PlayCommand playCommand = new PlayCommand(music);
PauseCommand pauseCommand = new PauseCommand(music);
NextCommand nextCommand = new NextCommand(music);
PreviousCommand previousCommand = new PreviousCommand(music);
// 设置命令请求者可以执行的命令
Invoker invoker = new Invoker();
invoker.setPlayCommand(playCommand);
invoker.setPauseCommand(pauseCommand);
invoker.setNextCommand(nextCommand);
invoker.setPreviousCommand(previousCommand);
// 根据具体需求执行命令
invoker.play();
invoker.pause();
invoker.next();
invoker.previous();
}
}
测试结果
play
pause
next
previous
命令模式将系列操作进行了,逻辑调用十分复杂,但是在实际开发过程中,给我我们带来了十分的便利,例如更改播放的歌曲,只需在Music类中修改该则可,其他操作类不需做出修改。
同时,在请求者里面,可以记录所有的操作对象,可以方便的知道执行的命令,方便的取消部分操作等,并且可以在需要时回复操作,提高了代码的灵活性。