设计模式-行为模式(Command)

原创 2005年05月23日 15:45:00

设计模式-行为模式(Command)

1、  定义:

把请求封装成一个可重用的对象,对于每次请求,这些对象的行为都可以被参数化。并且支持可取消的操作。

《设计模式的有趣解释-追MM》中解释:Command—俺有一个mm家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我。这不,她弟弟又传送过来一个command,为了感谢他,我请他吃了碗杂酱面,哪知道他说:我同时给我姐姐三个男朋友送command,就数你最小气,才请我吃面。

      命令模式:命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式允许请求的一方和发送的一方独 立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收 ,以及操作是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。

这是Command模式的UML图:

2、  适用性:

JAVASWING的组件中对Command模式的运用非常多,像菜单(MenuItem)对象那样,抽象出待执行的动作以参数化某对象。你可用过程语言中的回调(Callback)函数表达这种参数化机制。所谓回调函数是指函数先在某处注册,而它将在稍后某个需要的时候被调用。Command 模式是回调机制的一个面向对象的替代品。

在不同的时刻指定、排列和执行请求。一个Command 对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可将负责该请求的命令对象传送给另一个不同的进程并在那儿实现该请求。

支持取消操作。Command Excecute操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。Command 接口必须添加一个UnExcecute 操作,该操作取消上一次Excecute 调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并分别调用UnExcecute Excecute 来实现重数不限的取消重做

支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。在Command 接口中添加装载操作和存储操作,可以用来保持变动的一个一致的修改日志。从崩溃中恢复的过程包括从磁盘中重新读入记录下来的命令并用Excecute 操作重新执行它们。

用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务( transaction)的信息系统中很常见。一个事务封装了对数据的一组变动。Command 模式提供了对事务进行建模的方法。Command 有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。

3、  经典应用

Struts中的Action的设计就采用了这个模式:
    protected ActionForward
        processActionPerform(HttpServletRequest request, HttpServletResponse response, Action action, ActionForm form, ActionMapping mapping) throws IOException, ServletException {
        try {
            return (action.execute(mapping, form, request, response));
        } catch (Exception e) {
            return (processException(request, response, e, form, mapping));
        }
    }
    Action
是一个接口,每一个实现它的对象都必须实现execute方法,在执行这个函数之前,已经通过Action action = processActionCreate(request, response, mapping);得到客户端所请求的action对象。客户端通过login.do形式发送给ActionServlet,就可以调用LoginAction对象,通过search.do的形式就能调用SearchAction对象,而ActionServlet不用知道客户端发送的是什么请求。

4、  经典实现-用Command的模式实现Redo/Undo功能

设计了如下一个通用接口(封装用户请求的命令):
public Interface Command
{      

//执行用户当前指令,比如(copypastecutdelete)等
public void execute();

//返回上一操作
public void undo();

//返回下一操作
public void redo();

}

设计一个管理用户操作指令的接口CommandManager(管理用户所有的操作,以便支持取消操作):
public Interface CommandManager
{

//保存用户操作的指令
      public void storeCommand(Command cmd);

//清除用户所有操作指令
      public void clearAllCommand();

//返回用户上一操作
      public void undo();

//返回用户下一操作
      public void redo();
}

现在来实现一个用户命令:
public class DeleteCommand implements Command
{

    public void execute()
    {
        /*
备份上次操作后数据数据 */
        /*
执行用户新的指令(删除、粘贴等操作) */

    }

public void undo()
    {
         /* 
返回用户上次的数据  */
    }

public void redo()
    {
         /* 
返回用户下次的数据  */
    }

}

这样的话我们每做一个编辑动作,就执行一个相应的command.接下来我们要考虑如何将这些执行过的命令保存下来,以实现undo/redo

public class CommandHistoryManager implements CommandManager
{
 Vector undoList=new Vector();
 Vector redoList=new Vector();
 
 public void storeCommand(Command cmd)
 {
  undoList.add(cmd);
 }
 public void clearAllCommand()
 {
  undoList.clear();
  redoList.clear();
 }
 public void undo()
 {
        if ( undoList.size() <= 0 ) return;
        Command cmd = ((Command)(undoList.get(undoList.size()-1)));
        cmd.undo();
        undoList.remove(cmd);
        redoList.add(cmd);
 }
 public void redo()
 {
        if ( redoList.size() <= 0 ) return;
        Command cmd = ((Command)(redoList.get(redoList.size()-1)));
        cmd.execute();
        redoList.remove(cmd);
        undoList.add(cmd);
 }
}

通过storeCommand()方法,每次执行的command就可以保存到undoList中,假设再在我们在程序中放置了两个按钮,一个undo,一个redo.按下undo按钮,就执行CommandHistoryManager的undo()方法,undo()方法会调用undoList中保存的最后一个command的undo()方法,并将这个command再放到redoList中,最后从undoList中删除这个命令。这时如果再按redo按钮,它会调用CommandHistoryManager中的redo()方法。redo()方法会调用redoList中保存的最后一个command的execute()方法,并将这个command又存回到undoList中。这样就实现了无限次数的undo/redo功能。

参考:http://www.csdn.com.cn/program/2769.htm

设计模式(18)-Command Pattern

今天查看QT5的帮助文档,发现里面有提到Command Pattern,就查了下,发现这居然是一个设计模式,以前一直都在用,但还真不知道居然也是个设计模式。转了篇文章过来,以便记录。 htt...
  • zhgn2
  • zhgn2
  • 2012年03月28日 16:44
  • 403

设计模式(18)-Command Pattern

一、 命令(Command)模式 命令(Command)模式属于对象的行为模式【GOF95】。命令模式又称为行动(Action)模式或交易(Transaction)模式。命令模式把一个请求或者操作封...

设计模式 ( 十三 ) 命令模式Command(对象行为型)

设计模式 ( 十三 ) 命令模式Command(对象行为型) 1.概述         在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作...
  • hguisu
  • hguisu
  • 2012年05月09日 16:31
  • 18371

设计模式(行为型)之命令模式(Command Pattern)

在软件开发中,我们经常需要向某些对象发送请求(调用其中的某个或某些方法),但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,此时,我们特别希望能够以一种松耦合的方式来设计软件,使得请求发送者与...

【设计模式】行为模式之Command命令

Command命令是一种对象行为型设计模式,目的是将一个请求封装为一个对象,从而使得可用不同的请求对客户进行参数化,而且对请求排队或记录请求日志,以及支持可撤销的操作。在面向过程语言中的回调机制,如C...
  • iEearth
  • iEearth
  • 2016年08月21日 21:59
  • 454

设计模式(4)-行为型-命令模式(Command)

> 意图: 将一个请求封装为一个对象(即我们创建的Command命令对象),从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作。 个人理解: 命令模式是为了解...

"围观"设计模式(23)--行为型之命令模式(Command Pattern)

在面向对象程式设计的范畴中,命令模式是一种设计模式,它尝试以物件来代表实际行动。命令物件可以把行动(action) 及其参数封装起来,于是这些行动可以被: 重复多次取消(如果该物件有实作的话)取消后...

JAVA设计模式(15):行为型-命令模式(Command)

装修新房的最后几道工序之一是安装插座和开关,通过开关可以控制一些电器的打开和关闭,例如电灯或者排气扇。在购买开关时,我们并不知道它将来到底用于控制什么电器,也就是说,开关与电灯、排气扇并无直接关系,一...

设计模式(14)-行为型-命令模式(Command)

概述将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。适用性抽象出待执行的动作以参数化某对象,你可用过程语言中的回调(c a l l b...
  • iihero
  • iihero
  • 2012年11月22日 06:29
  • 1864

23种设计模式(14)_行为型_命令模式(Command Pattern)

定义:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。命令模式的封装性很好:每个命令都被封装起来,对于客户端来说,需要什么功能...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式-行为模式(Command)
举报原因:
原因补充:

(最多只允许输入30个字)