Java设计模式:命令模式
来源:互联网 发布:java compareto 排序 编辑:程序博客网 时间:2024/05/16 17:48
1.命令模式
命令模式(Command)属于对象的行为模式。
命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
2.命令模式的类图
参与的角色:
- Client:客户角色,创建了一个具体命令(ConcreteCommand)对象并确定其接收者。
- Command:命令角色:抽象命令接口,定义了命令的行为。
- ConcreteCommand:具体命令。定义一个接受者和行为之间的弱耦合;实现执行方法execute,负责调用接收者的相应操作。
- Invoker:请求者角色。负责调用命令对象执行请求,相关方法叫做行动方法action。
- Receiver:接收者角色。负责具体实施和执行一个请求。
3.示例代码
Client(客户端)
public class Client{ public static void main(String[] args) { /** * 命令使用顺序,创建接收者,如果没有接收者(可以没有接收者),创建命令,请求者,然后调用请求者执行行动. */ Receiver receiver = new Receiver(); Command command = new ConcreteCommand(receiver); Invoker invoker = new Invoker( command ); invoker.action(); } }
Command(抽象命令)
public interface Command { void execute();}ConcreteCommand(具体命令)
public class ConcreteCommand implements Command{ public ConcreteCommand(Receiver receiver) { this.receiver = receiver; } /** * 执行方法 */ public void execute() { receiver.action(); } private Receiver receiver;}Invoker(请求者)
public class Invoker{/** * 构造 * @param command */ public Invoker(Command command) { this.command = command; } public void action() {command.execute(); } private Command command;}Receiver(接收者),命令的具体执行者
public class Receiver{ public Receiver() { } /** * 行动方法 */ public void action() { System.out.println("Action has been taken."); }}
4.一个例子:操作录音机
系统需求
有一种录音机,录音机有播音(play)、倒带(rewind)和停止(功能)。用Java语言模拟这个系统。
录音机的键盘是请求者(invoker)角色;使用者是客户;而录音机是接收者角色。提炼一个抽象类Command扮演抽命令,此系统有PlayCommand,StopCommand和RewindCommand3个具体命令。
系统类图
如下:
代码实现
Keypad(请求者)
/** * 接收者角色 */public class Keypad{ private Command playCmd; private Command rewindCmd; private Command stopCmd; /** * 构造函数,参数是命令 * @param play * @param stop * @param rewind */public Keypad(Command play, Command stop, Command rewind){ // concrete Command registers itself with the invokerplayCmd = play;stopCmd = stop; rewindCmd = rewind;}//执行方法public void play(){playCmd.execute();}public void stop(){stopCmd.execute();} public void rewind() { rewindCmd.execute(); }}
Command(抽象命令)
/** * 抽象命令 */public interface Command{public abstract void execute ( );}PlayCommand(具体命令)
public class PlayCommand implements Command{private AudioPlayer myAudio;public PlayCommand ( AudioPlayer a) {myAudio = a;}public void execute( ) {myAudio.play();}}StopCommand(具体命令)
public class StopCommand implements Command{ private AudioPlayer myAudio; public StopCommand ( AudioPlayer a) {myAudio = a;}public void execute( ) {myAudio.stop();}}
RewindCommand(具体命令)
public class RewindCommand implements Command{private AudioPlayer myAudio;public RewindCommand ( AudioPlayer a) { myAudio = a;}public void execute() { myAudio.rewind();}}
AudioPlayer(接收者)
public class AudioPlayer{public void play( ){System.out.println("Playing...");}public void rewind( ){System.out.println("Rewinding...");}public void stop(){System.out.println("Stopped.");} }
Client(客户端)
/** * 客户端 */public class Client{ /** *键盘,持有Invoker角色 */ private static Keypad keypad ; /** *接受者角色 */ private static AudioPlayer myAudio = new AudioPlayer();public static void main(String[] args){ test1();} private static void test1() { Command play = new PlayCommand(myAudio); Command stop = new StopCommand(myAudio); Command rewind = new RewindCommand(myAudio); keypad = new Keypad(play, stop, rewind); keypad.play(); keypad.stop(); keypad.rewind(); keypad.stop(); keypad.play(); keypad.stop(); }}
运行效果:
Playing...
Stopped.
Rewinding...
Stopped.
Playing...
Stopped.
Stopped.
Rewinding...
Stopped.
Playing...
Stopped.
添加宏命令
设想:添加一个宏命令键,把设置好的命令按顺序执行。只需要增加一个宏命令,而不用修改接收者。增加宏命令,使用组合模式。
MacroCommand(宏命令的接口)继承与Command,增加了操作子命令的接口。
public interface MacroCommand extends Command{void execute();void remove(Command toRemove);void add(Command toAdd);}
MacroAudioCommand(宏命令实现)
public class MacroAudioCommand implements MacroCommand{ private List<Command> commandList = new ArrayList<Command>(); public void add(Command toAdd) { commandList.add(toAdd); } public void remove(int index) {commandList.remove(index); } public void remove(Command toRemove) {commandList.remove(toRemove); } public void execute() { Command nextCommand;/** * 子命令顺序执行 */for (int i=0; i < commandList.size(); i++){nextCommand = commandList.get(i);nextCommand.execute(); } } }
Client(客户端)
public class Client {/** * 键盘,持有Invoker角色 */private static Keypad keypad;/** * 接受者角色 */private static AudioPlayer myAudio = new AudioPlayer();public static void main(String[] args) {testMacroCommand();}private static void test1() {Command play = new PlayCommand(myAudio);Command stop = new StopCommand(myAudio);Command rewind = new RewindCommand(myAudio);keypad = new Keypad(play, stop, rewind);keypad.play();keypad.stop();keypad.rewind();keypad.stop();keypad.play();keypad.stop();}private static void testMacroCommand() {Command play = new PlayCommand(myAudio);Command stop = new StopCommand(myAudio);Command rewind = new RewindCommand(myAudio);MacroCommand macro = new MacroAudioCommand();macro.add(play);macro.add(stop);macro.add(rewind);macro.add(play);macro.add(stop);macro.add(rewind);macro.execute();}}
运行效果和test1一致。
5.让命令模式支持undo和redo
要让命令模式支持撤销和恢复功能,首先,抽象命令需要增加接口undo
public interface Command{public abstract void execute ( );public abstract void undo ( );}
然后,具体命令类需要存储状态信息,包括:
(1)接收者对象实际上实施请求所代表的的操作;
(2)对接收者对象所作出的操作所需要的参数;
(3)接收者类的最初的状态。接收者必须提供方法,使命令类可以控制接收者恢复原有状态。
最后,系统需要存储被执行过命令,当undo时,逆序遍历命令,执行undo,当redo时,顺序遍历命令,执行execute。
6.在什么情况下使用命令模式
- 使用命令模式作为callback在面向对象系统中的替代。callback讲的是:在面向过程编程中先将一个函数登记上,然后在以后调用此函数。
- 需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求者可以有不同的生命周期。
- 系统需要支持命令的撤销。
- 系统需要支持命令的redo,一个系统将所有的数据更新写到日志里,当系统崩溃时,可以读取日志,添加命令,然后redo,恢复数据。
7.命令模式的优点和缺点
优点:
- 命令模式把请求一个操作的对象(客户端)与知道怎么执行一个操作的对象(接收者)分开。
- 命令类容易修改和扩展。
- 容易实现合成命令
缺点:具体命令类可能有很多。
- java设计模式-命令模式
- java设计模式---命令模式
- java设计模式---命令模式
- 【java 设计模式】命令模式
- Java设计模式:命令模式
- java设计模式-----命令模式
- Java设计模式-命令模式
- java设计模式---命令模式
- Java设计模式--命令模式
- Java设计模式--命令模式
- JAVA设计模式-命令模式
- java设计模式,命令模式
- JAVA设计模式--命令模式
- Java设计模式-命令模式
- java设计模式-命令模式
- Java设计模式-命令模式
- JAVA设计模式-命令模式
- JAVA 设计模式 命令模式
- hotplug
- MySQL远程访问权限,允许远程连接的开启及局域网访问慢解决办法
- Adobe CS6和CS6.5官方简体中文英文原版版全系列迅雷下载地址
- sublime text2 用ctags插件实现方法定位
- 面试常见问题的经典回答 from http://www.nowamagic.net/
- Java设计模式:命令模式
- Java基础<八>_字符串
- Flex中将wmode设置为Opaque或Transparent时,鼠标滑轮mouseWheel事件失效的解决方法。
- MiniGUI源码分析——开始篇
- java_web学习第九天(JDBC数据库驱动------基础知识)
- Android makefile文件详解
- php无限循环分类小例子
- spring mvc 文件上传下载
- ZOJ 1926 Guessing Game