第17章 命令模式【Command Pattern】
·
基本介绍
命令模式(Command Pattern)是对命令的封装,每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式解耦了请求方和接收方,请求方只需请求执行命令,不用关心命令是怎样被接收,怎样被操作以及是否被执行.….等。命令模式属于行为型模式。
命令模式类图

从类图中我们可以看到命令模式主要包含四个角色:
- 接收者角色(Receiver):该类负责具体实施或执行一个请求
- 命令角色(Command):定义需要执行的所有命令行为;
- 具体命令角色( ConcreteCommand)该类内部维护一个接收者(Receiver)在其 execute()方法中调用 Receiver 的相关方法
- 请求者角色(Invoker):接收客户端的命令,并执行命令
命令模式案例举例
假如我们自己开发一个播放器,播放器有播放功能、有拖动进度条功能、停止播放功能、暂停功能,我们自己去操作播放器的时候并不是直接调用播放器的方法,而是通过一个控制条去传达指令给播放器内核,那么具体传达什么指令,会被封装为一个一个的按钮。那么每个按钮的就相当于是对一条命令的封装。用控制条实现了用户发送指令与播放器内核接收指令的解耦。
看代码:
/**
* 创建播放器内核
*/
public class GPlayer {
public void play(){
System.out.println("正常播放");
}
public void speed(){
System.out.println("拖动进度条");
}
public void stop(){
System.out.println("停止播放");
}
public void pause(){
System.out.println("暂停播放");
}
}
/**
* 命令接口
*/
public interface IAction {
void execute();
}
/**
* 播放指令
*/
public class PlayAction implements IAction{
private GPlayer gPlayer;
public PlayAction(GPlayer gPlayer) {
this.gPlayer = gPlayer;
}
@Override
public void execute() {
gPlayer.play();
}
}
/**
* 拖动进度条指令
*/
public class SpeedAction implements IAction{
private GPlayer gPlayer;
public SpeedAction(GPlayer gPlayer) {
this.gPlayer = gPlayer;
}
@Override
public void execute() {
gPlayer.speed();
}
}
/**
* 暂停指令
*/
public class PauseAction implements IAction{
private GPlayer gPlayer;
public PauseAction(GPlayer gPlayer) {
this.gPlayer = gPlayer;
}
@Override
public void execute() {
gPlayer.pause();
}
}
/**
* 拖动进度条指令
*/
public class StopAction implements IAction{
private GPlayer gPlayer;
public StopAction(GPlayer gPlayer) {
this.gPlayer = gPlayer;
}
@Override
public void execute() {
gPlayer.stop();
}
}
/**
* 创建控制条
*/
public class Controller {
private List<IAction> iActions = new ArrayList<>();
public void addAction(IAction iAction){
iActions.add(iAction);
}
public void execute(IAction iAction){
iAction.execute();
}
public void executes(){
for (IAction iAction : iActions) {
iAction.execute();
}
iActions.clear();
}
}
public class Client {
public static void main(String[] args) {
GPlayer gPlayer = new GPlayer();
Controller controller = new Controller();
controller.execute(new PauseAction(new GPlayer()));
System.out.println("----------------");
controller.addAction(new PlayAction(gPlayer));
controller.addAction(new PauseAction(gPlayer));
controller.addAction(new SpeedAction(gPlayer));
controller.addAction(new StopAction(gPlayer));
controller.executes();
}
}
运行结果:
暂停播放
----------------
正常播放
暂停播放
拖动进度条
停止播放
由于控制条已经与播放器内核解耦了,以后如果想扩展新命令,只需增加命令即可,控制条的结构无需改动。
命令模式在源码中的体现
- JDK中的Runnable接口,就是一个命令的抽象,实际上调用线程的start方法之后,线程就会去抢CPU资源,抢到资源后才会执行run()方法。所以Runnable接口把用户请求和CPU执行进行了解耦
更多推荐



所有评论(0)