设计模式学习总结-命令模式
1. 定义
把一个请求或者操作封装在命令对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
2. 要点
1) Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的实现手段是“将行为抽象为对象”。
2) 具体命令角色可以被不同的请求者角色重用。
3) 通过使用Compmosite模式,可以将多个命令封装为一个“复合命令”。
4) 增加新的具体命令角色很容易,因为这无需改变已有的类。
3. 适用性
1) 需要抽象出待执行的动作,然后以参数的形式提供出来——类似于过程设计中的回调机制。而命令模式正是回调机制的一个面向对象的替代品。
2) 在不同的时刻指定、排列和执行请求。一个命令对象可以有与初始请求无关的生存期。
3) 需要支持取消操作。
4) 支持修改日志功能。这样当系统崩溃时,这些修改可以被重做一遍。
5) 需要支持事务操作。
4. 结构图
1)命令角色(Command):声明执行操作的接口。有java接口或者抽象类来实现。
2)具体命令角色(Concrete Command):将一个接收者对象绑定于一个动作;调用接收者相应的操作,以实现命令角色声明的执行操作的接口。
3)客户角色(Client):创建一个具体命令对象(并可以设定它的接收者)。
4)请求者角色(Invoker):调用命令对象执行这个请求。
5)接收者角色(Receiver):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
5. 代码实例
要说例子,最合适不过的就是Struts1.X框架中的Action了。在Struts中Action(相当于Command角色),它连接着页面请求和后台业务逻辑处理。按照框架设计,每一个继承自Action的子类(相当于Concrete Command角色),都实现perform方法——调用后台真正处理业务的对象(相当于Receiver角色)来完成任务。我们在使用Struts的时候需要在web.xml中配置所有的HTTP请求都让ActionServlet处理(相当于Invoker角色),ActionServlet 是struts框架 MVC 实现的 controller 部分,它是这一框架的核心。ActionServlet把HTTP请求映射到相应的Action类,然后调用Action实例的perform()方法,将ActioForm bean,Action Mapping对象,request和response对象传给Action的perform()方法,perform返回一个ActionForword对象,根据方法执行情况转到相应的jsp页面。
由于Struts框架封装的很好,并且用到了多种设计模式,我还没有能力依依分析出来,下面找到了一个简单的命令模式实现的伪Servlet例子。原文英文地址在此。
// CommandExample.java //********************************* // Client 角色,调用者 //********************************* import java.util.HashMap; // ************************************************************************ /** * CommandExample.java * * Provides a simple Command Design Pattern Example. * * The example will show how to use the Command Design Pattern * by replacing conditional control logic in a simulated M-V-C Model * 2 servlet. So as not to need a webserver to implement this * example, a phamtom object will be created and passed in for * demonstration purposes. */ // ************************************************************************ public class CommandExample { public static void main(String[] args) { CommandExample.log(1,"Begin Command Design Pattern example."); ExampleServlet exampleServlet = new ExampleServlet(); int maxApproaches = 3; String exampleActionRequest = "update"; CommandExample.log(1,"Simulated servlet request received is: " + exampleActionRequest); CommandExample.log(1,"Code will show " + maxApproaches + " approaches as to how such a command can be processed."); for(int i=1; i<=maxApproaches; i++) { exampleServlet.doPost(i,exampleActionRequest); } //endfor CommandExample.log(1,"End Command Design Pattern example."); } //endmain // =================================================================== public static void log(int aLevel, String aMsg) { boolean showLogTraceToSystemOut = true; if(showLogTraceToSystemOut) { String prefix = ""; if(aLevel == 1) { prefix = " ---> "; } else if(aLevel == 2) { prefix = " ---> "; } else if(aLevel == 3) { prefix = " ---> "; } //endif System.out.println(prefix + aMsg); } //endif } //endmethod: log } //endclass: CommandExample.java |
//********************************* // 一个简化的Servlet,相当于Invoker角色 //********************************* // ************************************************************************ /** * ExampleServlet.java * * Simulates a servlet in an M-V-C Model 2 environment. * * @param action the desired action the servlet is to perform. */ // ************************************************************************ class ExampleServlet { private HashMap commandMap = new HashMap(); // =================================================================== public ExampleServlet() { //-- Initialize HashMap of possible ActionType concrete objects commandMap.put("create", new ActionTypeCreate()); commandMap.put("replace", new ActionTypeReplace()); commandMap.put("update", new ActionTypeUpdate()); commandMap.put("delete", new ActionTypeDelete()); } //endmain // =================================================================== public void doPost(int approachSolution, String action) { switch (approachSolution) { case 1: CommandExample.log(2, "Demonstrating from full conditional processing."); performTask1(action); break; case 2: CommandExample.log(2, "Demonstrating from abstracted concrete class processing."); performTask2(action); break; case 3: CommandExample.log(2, "Demonstrating from Command Design Pattern processing."); performTask3(action); break; } //endswitch } //endmethod: doPost // =================================================================== private void performTask1(String action) { //-- Process business logic within conditional statements if( action.equalsIgnoreCase("create") ) { CommandExample.log(3, "create business logic executing..."); } else if( action.equalsIgnoreCase("replace") ) { CommandExample.log(3, "replace business logic executing..."); } else if( action.equalsIgnoreCase("update") ) { CommandExample.log(3, "update business logic executing..."); } else if( action.equalsIgnoreCase("delete") ) { CommandExample.log(3, "delete business logic executing..."); } //endif } //endmethod: performTask1 // =================================================================== private void performTask2(String action) { //-- Abstracts out all business logic into separate classes ActionType cmd = null; if( action.equalsIgnoreCase("create") ) { cmd = new ActionTypeCreate(); } else if( action.equalsIgnoreCase("replace") ) { cmd = new ActionTypeReplace(); } else if( action.equalsIgnoreCase("update") ) { cmd = new ActionTypeUpdate(); } else if( action.equalsIgnoreCase("delete") ) { cmd = new ActionTypeDelete(); } //endif cmd.execute(); } //endmethod: performTask2 // =================================================================== private void performTask3(String action) { //-- Uses the Command Design Pattern to polymorphically //-- execute desired action ActionType cmd = (ActionType)commandMap.get(action); cmd.execute(); } //endmethod: performTask3 } //endclass: ExampleServlet |
//********************************* // Action抽象接口极其子类,Command角色的实现 //********************************* abstract class ActionType { abstract public void execute(); } //endclass: ActionType //**************************** class ActionTypeCreate extends ActionType { public void execute() { CommandExample.log(3, "ActionTypeCreate business logic executing..."); } //endmethod: execute } //endclass: ActionTypeCreate //**************************** class ActionTypeReplace extends ActionType { public void execute() { CommandExample.log(3, "ActionTypeReplace business logic executing..."); } //endmethod: execute } //endclass: ActionTypeReplace //**************************** class ActionTypeUpdate extends ActionType { public void execute() { CommandExample.log(3, "ActionTypeUpdate business logic executing..."); } //endmethod: execute } //endclass: ActionTypeUpdate class ActionTypeDelete extends ActionType { public void execute() { CommandExample.log(3, "ActionTypeDelete business logic executing..."); } //endmethod: execute } //endclass: ActionTypeDelete |