设计模式学习总结-命令模式

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

Leave a Comment.