命令(Command)模式属于对象的行为模式,把一个请求或者操作封装到一个对象中,允许系统使用不同的请求把客户端参数化,对请求排队或者记录到请求日志,可以提供命令的撤销和恢复功能。命令模式是对命令的封装,把发出的命令的责任和执行命令的责任分开,委派给不同的对象。
设计角色:
客户(Client)角色:创建一个具体命令对象并确定接收者。
命令(Command)角色:声明一个给所有具体命令的抽象接口。
具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现execute()方法,负责调用接受者的相应操作。execute方法通常叫做执行方法。
请求者(Invoker)角色:负责调用命令对象执行请求,相关方法叫做行动方法。
接收者(Reveiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
例子:
package cn.design.pattern.demo.command.client; import cn.design.pattern.demo.command.command.Command; import cn.design.pattern.demo.command.command.PlayCommand; import cn.design.pattern.demo.command.command.RewindCommand; import cn.design.pattern.demo.command.command.StopCommand; import cn.design.pattern.demo.command.invoker.Keypad; import cn.design.pattern.demo.command.reviever.AudioPlayer; /** * 客户端:创建命令和确定接收者 */ public class Client { private static Keypad keypad; private static AudioPlayer player = new AudioPlayer(); // 接收者 public static void main(String[] args) { test1(); test2(); } private static void test1() { // 创建三个命令并将接收者传入 Command play = new PlayCommand(player); Command stop = new StopCommand(player); Command rewind = new RewindCommand(player); keypad = new Keypad(play, rewind, stop); keypad.play(); keypad.stop(); keypad.rewind(); } private static void test2() { Command play = new Command() { @Override public void execute() { player.play(); } }; Command rewind = new Command() { @Override public void execute() { player.rewind(); } }; Command stop = new Command() { @Override public void execute() { player.stop(); } }; keypad = new Keypad(play, rewind, stop); keypad.play(); keypad.stop(); keypad.rewind(); } } package cn.design.pattern.demo.command.command; /** * 抽象命令角色 */ public interface Command { /** * 执行方法 */ public void execute(); } package cn.design.pattern.demo.command.command; import cn.design.pattern.demo.command.reviever.AudioPlayer; /** * 具体命令角色 * 定义一个接受者和行为之间的弱耦合 */ public class PlayCommand implements Command { private AudioPlayer audioPlayer; // 接收者 public PlayCommand(AudioPlayer audioPlayer) { this.audioPlayer = audioPlayer; } /** * 执行方法 */ @Override public void execute() { // 调用接收者相应方法,执行命令 audioPlayer.play(); } } package cn.design.pattern.demo.command.command; import cn.design.pattern.demo.command.reviever.AudioPlayer; /** * 具体命令角色 */ public class RewindCommand implements Command { private AudioPlayer audioPlayer; public RewindCommand(AudioPlayer audioPlayer) { this.audioPlayer = audioPlayer; } @Override public void execute() { audioPlayer.rewind(); } } package cn.design.pattern.demo.command.command; import cn.design.pattern.demo.command.reviever.AudioPlayer; /** * 具体命令角色 */ public class StopCommand implements Command { private AudioPlayer audioPlayer; public StopCommand(AudioPlayer audioPlayer) { this.audioPlayer = audioPlayer; } @Override public void execute() { audioPlayer.stop(); } } package cn.design.pattern.demo.command.invoker; import cn.design.pattern.demo.command.command.Command; /** * 请求者角色 * 负责调用命令对象执行请求 */ public class Keypad { private Command playCmd; // 命令对象 private Command rewindCmd; private Command stopCmd; public Keypad(Command play, Command rewind, Command stop) { this.playCmd = play; this.rewindCmd = rewind; this.stopCmd = stop; } /** * 行动方法 */ public void play() { // 执行命令请求 playCmd.execute(); } public void rewind() { rewindCmd.execute(); } public void stop() { stopCmd.execute(); } } package cn.design.pattern.demo.command.reviever; /** * 接收者角色 */ public class AudioPlayer { public void play() { System.out.println("播放"); } public void rewind() { System.out.println("倒带"); } public void stop() { System.out.println("停止"); } }
特点:
1.新的命令很容易地被加入到系统里.
2.允许接受请求的一方决定是否要否决请求.
3.可以方便地设置一个命令队列.
4.实现对请求的Undo和Redo.
5.比较容易地将命令计入日志.