command pattern

来源:互联网 发布:高可用mysql 第2版 pdf 编辑:程序博客网 时间:2024/05/16 08:40

很惭愧,读书的时候学过一点设计模式的知识后,就没有怎么好研究过,今天看到一句话:设计模式就好像是砍柴者的磨刀功一样,所以即使按不是一个优秀的程序员,但是也要把磨刀功学好吧^_^,从今天起好好学习设计模式哈,以做笔记来激励自己。。

这些都是我查资料整理的,顺便也加上了自己的一些实现。

命令模式:

命令Command模式是GOF23种模式中的一种,是一种行为模式。这种模式很难理解。《设计模式》一书中对它语焉不详。

GoF将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数华;对请求排队或记录请求日志,以及支持克撤销的操作。

 

我的理解:当有多个类似又有不同的东西(concrete command)需要做同样的处理(execute,该处理当然也随类的不同所有变化)的时候。省去if...else…

实际上,命令模式并不是那么神秘。

命令模式的理解,关键有2点:

一、使用接口---实现类的方式

  通常命令模式的接口中只有一个方法。

    实现类的方法有不同的功能,覆盖接口中的方法。

    在面向对象编程中,大量使用if…else…,或者switch…case…这样的条件选择语句是“最差实践”。通常这类代码,意味着有重构的余地。

命令模式就是干掉条件选择语句的利器。

1首先提供一个接口:

publicinterface Command {

publicvoid execute();

}

 

2然后提供这个接口的实现类。每一个实现类的方法就是if…else…的一个代码块中的代码。

这样,调用方直接把一个具体类的实例传进来即可。如:

Public void test(Command para){

   Para.execute();

}

    即可,不需要再判断出现了哪种情况,应该执行哪一段代码。

一切的问题都由调用方处理。

如果不使用命令模式,那么如果情况逐步增多,如,从原来的2种,增加到20种,那么方法中的判断就会从1次增加到19次。

而使用命令模式,仅仅调用方需要从2个实现类增加到20个实现类即可。上面的test方法根本不需要做任何改变。

 

二、主要的用途是,使用参数回调模式。

   最主要使用命令模式的方式是使用参数回调模式。

  命令接口作为方法的参数传递进来。然后,在方法体内回调该接口。

  上文的例子是如此,Swing的事件机制也是使用这种方法。

如:

publicinterface Command {

publicvoid execute();

}

 

publicvoid actionPerformed(ActionEvent e) {

Commandcmd = (Command)e.getSource();

cmd.execute();

}

 

当然,命令模式还可以使用其他方式来使用。不一定非用参数回调模式。

命令模式的核心思想是,带有某个方法的具体类的实例,作为接口传给使用方。对象的具体类型信息消失。

在使用方代码中拿到这个接口后调用这个接口的方法。

具体的执行效果,取决的命令发起人提供的对象是哪一个实现类的。这给了命令发起人完全的控制能力,而使用方代码不关心具体的命令类和方法。同时也使条件判断语句成为多余。

 

最简单的命令模式的实现代码如下:

///定义Command接口

public interface ICommand

{

    public void execute();

}

 

///实现ICommand接口

///Command类是所有命令的基类,在这里实现一些命令的共同处理过程

public abstract class Command implements ICommand

{

    public void execute()

    {

    }

    //实现其他的方法....

}

 

///实现一个具体的Command1

public class Command1 extends Command

{

    public void execute()

    {

        //具体的处理过程

    }

}

 

///实现一个具体的Command2

public class Command2 extends Command

{

    public void execute()

    {

        //具体的处理过程

    }

}

 

///实现一个具体的Command3

public class Command3 extends Command

{

    public void execute()

    {

        //具体的处理过程

    }

}

 

//test

public class comTest {

 

       static void test(Command command){

              command.execute();

       }

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

 

              Command1 c1=new Command1 ();

              Command2 c2=new Command2 ();

              test(c1);

              test(c2);

             

       }

 

}

 

下面给出UML图,看一下他们之间的关系:

command_pattern_UML

例子2

 

先定义关键的Command抽象类(这里也可以用接口):
package Command;

public abstract class Command
...{
    
protected Receiver receiver; 
 
    
public Command(Receiver receiver) 
    
...
        
this.receiver = receiver; 
    }
//end Command(...)

    
abstract public void execute();
    
}
//end abstract class Command

再继承一个具体类:
package Command;

public class ConcreteCommand extends Command
...{
    
    
public ConcreteCommand( Receiver receiver )
    
...{
        
super(receiver);
    }
//end ConcreteCommand(...)
 
    
public void execute() 
    
...
        receiver.action(); 
    }
//end execute()

}
//end class ConcreteCommand

定义一个Receiver类:
package Command;

public class Receiver
...{
    
public void action() 
    
...
        System.out.println("Receiver.Action()");
    }
//end Action()
    
}
//end class Receiver

定义一个Invoker类:
package Command;

class Invoker 
...
    
private Command command; 

    
public void setCommand( Command command ) 
    
...
        
this.command = command; 
    }
//end setCommand(...)

    
public void executeCommand() 
    
...
        command.execute(); 
    }
//end executeCommand()
    
}
//end class Invoker

最后是调用:
package Command;

public class CommandPattern
...{
    Receiver rceiver = 
new Receiver(); 
    Command command = 
new ConcreteCommand(rceiver); 
    Invoker invoker = 
new Invoker();

    
/** *//** Creates a new instance of CommandPattern */
    
public CommandPattern()
    
...{
        
    }
//end CommandPattern
    
    
public void showCommandPattern()
    
...{
        invoker.setCommand(command);
        invoker.executeCommand();
    }
//end showCommandPattern()
    
    
public static void main(String[] args)
    
...{
        System.out.println("----------------------");
        System.out.println("The Command Pattern!");
        CommandPattern cp = 
new CommandPattern();
        cp.showCommandPattern();
        System.out.println("----------------------");
    }
//end main(...)
    
}
//end class CommandPattern

 

 

struts中的使用:

StrutsAction控制类是整个框架的核心,它连接着页面请求和后台业务逻辑处理。按照框架设计,每一个继承自Action的子类,都实现execute方法——调用后台真正处理业务的对象来完成任务。

注:继承自DispatchAction的子类,则可以一个类里面处理多个类似的操作。这个在这不做讨论。

 

     下面我们将Struts中的各个类与命令模式中的角色对号入座。

     先来看下命令角色——Action控制类

publicclass Action {

      ……

        /*

        *可以看出,Action中提供了两个版本的执行接口,而且实现了默认的空实现。

      */

public ActionForward execute( ActionMapping mapping,

                                                ActionForm form,

                                                ServletRequest request,

                                                ServletResponse response)

       throws Exception {

       try {

           return execute(mapping, form, (HttpServletRequest) request,

                                   (HttpServletResponse) response);

       } catch (ClassCastException e) {

           return null;

       }

   }

 

public ActionForward execute( ActionMapping mapping,

                                                ActionForm form,

                                                 HttpServletRequest request,

                                                HttpServletResponse response)

       throws Exception {

       return null;

   }

}

 

下面的就是请求者角色,它仅仅负责调用命令角色执行操作。

publicclass RequestProcessor {

……

protected ActionForwardprocessActionPerform(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));

       }

}

}

 

Struts框架为我们提供了以上两个角色,要使用struts框架完成自己的业务逻辑,剩下的三个角色就要由我们自己来实现了。步骤如下:

1)很明显我们要先实现一个Action的子类,并重写execute方法。在此方法中调用业务模块的相应对象来完成任务。

2)实现处理业务的业务类。

3)配置struts-config.xml配置文件,将自己的ActionForm以及相应页面结合起来。

4)编写jsp,在页面中显式的制定对应的处理Action

一个完整的命令模式就介绍完了。当你在页面上提交请求后,Struts框架会根据配置文件中的定义,将你的Action对象作为参数传递给RequestProcessor类中的processActionPerform()方法,由此方法调用Action对象中的执行方法,进而调用业务层中的接收角色。这样就完成了请求的处理。

 

原创粉丝点击