Command模式
来源:互联网 发布:韩国网络作家 编辑:程序博客网 时间:2024/06/06 18:00
Command模式是指用一个对象来表示和封装要调用的方法的所有信息,这个方法会在之后的某个时间执行。这些信息包括方法名字, 那个对象拥有这个方法,方法的参数。这种模式中有三种角色,client, invoker 和 receiver。 client用来实例化command对象,并提供被调用方法的所有信息。invoker会决定什么时候执行command对象对应的实际方法。receiver是指拥有该实际方法的实例,主要的逻辑处理也将在receiver拥有的这个方法里面执行。
使用command模式可以很容易构造通用的组件,这些组件可用于实现方法的代理,方法序列,或需要在将来的某个特定时间执行的方法。调用者(invoker)不需要知道实际被调用方法的所有者是谁,需要哪些参数等。
用途:
1. 复杂的undo(Multi-level undo)
如果所有用户的操作都以一个command对象来实现,程序中可以保留一个存放command对象的堆栈。如果用户需要取消(undo)一个操作,程序可以堆栈中取出最近的command,运行command对象中对应的undo方法。
2. 事务处理(Transactional behavior)
和undo的实现类似,程序中可以保存一个事务内相关操作的列表,如果其中一个操作失败,那么则回滚列表内其他已经执行了的操作。
3. 进度条的实现(Progress bars)
假设一个程序中要顺序执行一系列操作,如果每一个操作(具体的command对象)都实现了getEstimatedDuration()方法,那么在此程序中就很容易计算出这一系列操作完成需要的总时间。进而进度条就可以反映出这一系列操作的完成情况。
4. Wizards
wizards通常表示一个配置需要分几个页面(步骤)来完成,比如填写简历,第一页填写基本信息,下一页是工作经历,等等。利用command模式的话,就可以把每一步用一个command对象来实现,当用户最后完成所有步骤并确认时,这时才依次调用command的execute方法。
5. 按钮和菜单项(GUI buttons and menu items)
在Swing中,一个Action就是一个command对象。一个Action可能需要包含一个icon,快捷键,tooltip等信息。一个工具栏或菜单的实现就需要使用Action对象。
6. 线程池(Thread pools)
通常一个线程池类会有一个addTask()方法,用来添加一个任务到一个内部队列中,在队列中task就实现为一个command对象,通常这个时候,command类会实现java.lang.Runnable接口,可以使线程池执行对应的command,线程池不需要知道所执行的任务(即command)的具体信息。
7. 网络应用(networking)
command对象可以通过网络传送到其他机器,比如在一些网络游戏中的应用。
8. 并行处理(Parallel Processing)
任务可以被实现为一个command对象,并作为一个共享资源,被多个线程同时调用,例如在Master/worker模式下,还可以被远程调用。
command模式的结构:
图解:
Command为接口,ConcreteCommand实现Command接口,并实现execute方法.
在ConcreteCommand.execute()方法会调用Receiver中的Action()方法,真正的逻辑实现是发生在Receiver.Action()方法中,所以ConcreteCommand类是依赖与Receiver的。
在Invoker中会保存一系列需要执行的Command对象,所以Invoker和Command是组合的关系。
在Client中会初始化Receiver和Command对象,所以client和Receiver和ConcreteCommand都是依赖的关系。
(注:可以是由client来把command对象添加到invoker的command集合中,或是有invoker主动监听的方式,或是别的方式,这里视情况而定)。
实例:
电源开关的例子:
/*the Command interface*/public interface Command { void execute();} /*the Invoker class*/import java.util.List;import java.util.ArrayList; public class Switch { private List<Command> history = new ArrayList<Command>(); public Switch() { } public void storeAndExecute(Command cmd) { this.history.add(cmd); // optional cmd.execute(); } } /*the Receiver class*/public class Light { public Light() { } public void turnOn() { System.out.println("The light is on"); } public void turnOff() { System.out.println("The light is off"); } } /*the Command for turning on the light - ConcreteCommand #1*/public class FlipUpCommand implements Command { private Light theLight; public FlipUpCommand(Light light) { this.theLight = light; } public void execute(){ theLight.turnOn(); } } /*the Command for turning off the light - ConcreteCommand #2*/public class FlipDownCommand implements Command { private Light theLight; public FlipDownCommand(Light light) { this.theLight = light; } public void execute() { theLight.turnOff(); } } /*The test class or client*/public class PressSwitch { public static void main(String[] args){ Light lamp = new Light(); Command switchUp = new FlipUpCommand(lamp); Command switchDown = new FlipDownCommand(lamp); Switch s = new Switch(); try { if (args[0].equalsIgnoreCase("ON")) { s.storeAndExecute(switchUp); System.exit(0); } if (args[0].equalsIgnoreCase("OFF")) { s.storeAndExecute(switchDown); System.exit(0); } System.out.println("Argument \"ON\" or \"OFF\" is required."); } catch (Exception e) { System.out.println("Argument's required."); } } }
- Command模式
- Command模式
- Command模式
- Command 模式
- Command 模式
- Command模式
- command模式
- Command模式
- Command模式
- Command模式
- Command 模式
- Command 模式
- Command模式
- Command模式
- Command模式
- COMMAND 模式
- Command模式
- Command模式
- 简单看了一下源码的实现,这里贴一点个人觉得比叫重要的代码。
- git 使用详解(8)-- 分支HEAD
- Facebook成功分析
- Linux的用户和组
- 调用系统相机拍照和选择相册
- Command模式
- 【Visual C++】游戏开发笔记十七 游戏基础算法(一) 游戏随机系统初步
- ZFS源代码之旅——ZAP模块分析(一)
- linux网络环境配置
- 贪心算法最短路径
- Asterisk的conf文件格式的官方说明中文板
- java 垃圾回收中的root是个什么玩意儿?
- J - Perfect Pth Powers解题报告(陈渊)
- Data Driven Document - D3js