Command模式二

 

 

 假设现有一个新需求要求我们统计方法的执行时间.假设已有一个Command接口,其主要代码如下所示:

  

Java代码 复制代码
public abstract void execute();

 还有一个Command Timer类:

Java代码 复制代码
package com.oozinoz.utility;

import com.oozinoz.robotInterpreter.Command;

public class CommandTimer
{
	public static long Time(Command command){
		long t1 = System.currentTimeMillis();
		command.execute();
		long t2 = System.currentTimeMillis();
		return t2-t1;
	}
}

可以使用JUnit测试来测试time()方法,代码类似于下面的语句.请注意,这不是准确的测试;如果计时器是"jittery",程序就会失败.

package app.command;

import com.oozinoz.robotInterpreter.Command;
import com.oozinmoz.utility.CommandTimer;

import junit.framework.TestCase;

public class TestCommandTimer extends TestCase
{
	public void testSleep(){
		Command doze = new Command(){
			public void execute(){
				try
				{
					Thead.sleep(2000 + Math.round(10 * Math.random()));
				}
				catch (InterruptedException ignored)
				{
				}
			}
		};

	long acture = CommandTimer.time(doze);   //突破题答案

	long expected = 2000;
	long delta = 5;

	assertTrue("Should be " + expected + "+/-" + delta + " ms",expected - delta <= actual && actual <= expected + delta);
	}
}

 

突破题:请填写完整上面用于统计doze命令执行时间的赋值语句.

答:testSleep()方法将doze命令传递给CommandUtil类的time()工具方法.如上面注释部分所示.

 

3.Command模式钩子:

  前面介绍了Aster火药球填压机,它是一种智能机器,其代码应用了Template Method模式.在该代码中,我们重写了其中的markMoldIncomplete()方法;当我们关闭填压机的时候,如果正在处理模具,那么该方法则会将该模具标识为未完成的模具.

 AsterStarPress类是一个抽象类,在它的子类中,我们必须重写markMoldIncomplete()方法,AsterStarPress类的shutdown()方法就是依赖这个方法来确保域对象知道哪些模具是未完成的.

 

Java代码 复制代码
public void shutdown(){
  if(inProcess()){
    stopProcessing();
	markMoldIncomplete(currentMoldID);
  }
  usherInputMolds();
  dischargePaster();
  flush();
}

我们会将有些类移到火药球填压机的板载计算机上,因而由AsterStarPress类派生出子类可能会不方便.假设我们要求AsterStarPress类的开发人员应用Command模式来提供一个钩子.图1描述了一个Hook命令,AsterStarPress类可以使用这个命令,这样我们就可以将焰火填压机的代码在运行时参数化.


我们可以在类中提供一个钩子,从而允许用户插入定制的代码.

所谓的钩子就是在某段代码的特定位置调用用户提供的命令

 

 

  最初,AsterStarPress类将它的钩子设置为NullHook对象.这个NullHook对象的execute()方法并不执行任何操作.我们可以提供自己实现的Hook对象,以便shutDown()方法调用.在本例中,shutDown()方法将在适当的时刻以AsterStarPress对象为参数调用钩子的特定方法,具体代码如下:

Java代码 复制代码
public void shutDown(){
	if(inProcess()){
		stopProcessing();
		moldIncompleteHook.execute(this);   //突破题要求完成的语句
	}
	usherInputMolds();
	dischargePaste();
	flush();
}

 

请注意,这个方法并没有干扰检测moldIncompleteHook是否是null,因为始终被设置为一个真实的Hook对象(最初它被设置为不做任何事情的NullHook对象,用户可以配置不同的钩子).

它的用法如下:

Java代码 复制代码
package app.templateMethod;

import com.oozinoz.businessCore.*;
import aster2.*;

public class ShowHook
{
	public static void main(String[] args)
	{
		AsterStarPress p = new AsterStarPress();
		Hook h = new Hook(){
			public void execute(AsterStarPress p){
				MaterialManager m = MaterialManager.getManager();
				m.setMoldIncomplete(p.getCurrentMoldID());
			}
		};
		p.setMoldIncompleteHook(h);
	}
}

 

突破题:请完成shutDown()方法的代码.

 

  本例演示了另外一个模式,NULL Object模式,这个模式没有<<设计模式>>一书中的模式那么著名.通过引入默认的对象,该模式可以避免空指针检查.

  Command模式提供除Template Method模式之外的另一种设计钩子的方法.此外,Command模式在设计意图或者设计结构上非常类似于其他几种设计模式.

 

4.Command模式与其他模式的关系:

  Command模式类似于Interpreter模式.这两个模式将在下一章进一步进行比较.Command模式也类似于我们前面介绍的一个模式,客户知道应该在何时创建对象,但并不知道该实例化哪个类.?

 

突破题:请问在哪个模式中,客户知道应该在何时创建对象,但并不知道该实例化哪个类?

答:在Factory Method模式中,用户知道何时创建一个新的对象,但并不知道该创建一个什么类型的对象.Factory Method模式将创建对象的工作移入另一个方法中,从而使得用户无需知道该对哪个类进行实例化.这一原则同样适用于Abstract Factory模式.

 

除了类似于其他模式之外,Command模式通常和其他模式合作使用.比如,你也许在MVC设计中同时使用Command模式和Mediator模式.Mementos模式里就给出这样一个例子.Visualization类处理GUI控制逻辑,但是中介者负责任何与模型相关的逻辑处理.比如,Visualization类使用如下代码来滞后实例化Undo按钮:

Java代码 复制代码
protected JButton undoButton()
{
	if(undoButton == null){
		undoButton = ui.createButtonCancel();
		undoButton.setText("undo");
		undoButton.setEnabled(false):
			undoButton.addActionListener(mediator.undoAction());
	}
	return undoButton;
}

  上述代码应用了Command模式,把undo()方法打包放在ActionListener类的一个实例中.这部分代码也使用Mediator模式,让中心对象处理与底层对象模型相关的事件.为保证undo()方法正确工作,中介者代码必须恢复模拟工厂的以前版本,保证应用经常与Command模式一起使用的其他模式.

  

突破题:请问哪种模式可以实现对象状态的存储和恢复?

答:Memento模式的意图在于为对象状态提供存储和恢复的机制.通常,每当执行一个命令的时候,就向栈中压入一个新的备忘录;当用户需要撤销前面所执行的命令的时候,可以从栈中弹出一个备忘录,并将它应用于当前的程序.

 

5.小结

 Command模式将请求封装在对象中,这样就可以像管理对象一样管理调用,当时机和环境适合时进行调用.菜单是Command模式的一个典型实例,它能够充分体现该模式的价值.在菜单的设计中,菜单项知道应该在何时执行操作,但是并不知道将会调用哪个方法.我们通过应用Command模式可以将菜单项对应的方法调用作为参数传给菜单.

 Command模式的另外一个用法是允许在服务的上下文中执行客户代码.服务经常在客户代码调用前和调用后运行.最后,除了控制方法执行的时机或者上下文之外,Command模式还可以提供钩子,允许可选的客户代码作为算法的一部分执行.

 Command模式把请求封装在一个对象中,所以可以像操作其他对象一样来管理它.可能是由于Command模式所应用的都是一些非常基础的思想,因而它与其他许多设计模式都存在着有趣的联系.比如,Command模式可以作为Template Method模式的一种替代模式,此外,该模式还可以与Mediator模式和Memento模式共同使用.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值