命令模式是对命令的封装, 每一个命令都是一个操作,请求的一方发出请求要求执行一个操作, 接受的一方收到请求, 并
执行操作。命令模式解耦了请求方和接收方, 请求方只需请求执行命令, 不用关心命令是怎样被接收,怎样被操作以及是否被执行等
特征:解耦命令请求与处理;属于行为型模式
使用场景:
1、现实语义中具备"命令"的操作(命令菜单,shell命令)
2、请求调用者和请求接受者需要解耦, 使得调用者和接受者不直接交互
3、需要抽象出等待执行的行为, 比如撤销(Undo)操作和恢复(Redo)等操作
4、需要支持命令宏(命令组合操作)
public interface ICommand { /** * 执行 */ void execute(); }
public class Invoker { private ICommand mCmd; public Invoker(ICommand mCmd) { this.mCmd = mCmd; } public void action(){ this.mCmd.execute(); } }
public class Receiver { public void action(){ System.out.println("执行具体操作"); } }
public class ConcreteCommand implements ICommand{ private Receiver receiver = new Receiver(); @Override public void execute() { receiver.action(); } }
public static void main(String[] args) { ICommand command = new ConcreteCommand(); Invoker invoker = new Invoker(command); invoker.action(); }
=======================================================================================
public class Player { 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 PauseAction implements IAction { private Player player; public PauseAction(Player player) { this.player = player; } @Override public void execute() { player.pause(); } }
public class StopAction implements IAction { private Player player; public StopAction(Player player) { this.player = player; } @Override public void execute() { this.player.stop(); } }
public class SpeedAction implements IAction { private Player player; public SpeedAction(Player player) { this.player = player; } @Override public void execute() { this.player.speed(); } }
public class PlayAction implements IAction { private Player player; public PlayAction(Player player) { this.player = player; } @Override public void execute() { this.player.play(); } }
public class Controller { private List<IAction> actions = new ArrayList<>(); public void addAction(IAction action) { actions.add(action); } public void execute(IAction action) { action.execute(); } public void executes(){ for (IAction action: actions) { action.execute(); } actions.clear(); } }
public static void main(String[] args) { Player player = new Player(); Controller controller = new Controller(); controller.execute(new PauseAction(player)); controller.addAction(new PauseAction(player)); controller.addAction(new PlayAction(player)); controller.addAction(new StopAction(player)); controller.addAction(new SpeedAction(player)); controller.executes(); }
源码中的实现: Runnable接口; Junit包下面的Test接口
优点:
1、通过引入中间件(抽象接口), 解耦了命令请求与实现
2、扩展性良好, 可以很容易地增加新命令
3、支持组合命令, 支持命令队列
4、可以在现有命令的基础上, 增加额外功能(日志记录等, 结合装饰器模式更好)
缺点:
1、具体命令类可能过多
2、增加了程序的复杂度, 理解更加困难
来源:oschina
链接:https://my.oschina.net/u/2954646/blog/3197038