Command 和 Active Object 模式

Command 和 Active Object 模式

Command 模式是封装了一个没有任何变量的函数。

public interface Command {
	public void do();
}

简单的Command

打印机工作流

开启/关闭继电器—RelayOnCommand、RelayOffCommand;

开启/关闭发动机—MotorOnCommand、MotorOffCommand;

开启/关闭离合器—ClutchOnCommand、ClutchOffCommand;

事务操作

        另一个Command 模式的常见用法是创建和执行事务操作(Transactions)。当用户决定增加一个新雇员时,该用户必须详细指明成功创建一条雇员记录所需的所有信息。在使用这些信息前,系统需要验证这些信息语法和语义上的正确性。Command 对象存储了还未验证的数据,实现了实施验证的方法,并且实现了最后执行事务操作的方法。

        validate() 方法检查所有数据并确保数据是有意义的。

        execute() 方法用已经验证过的数据去更新数据库。

 

Active Object 模式

        Active Object 模式是使用Command 模式的地方之一。这是实现多线程控制的一项古老的技术。

ActiveObjectEngine.java

import java.util.LinkedList;


public class ActiveObjectEngine {

	/**
	 * 命令链表.
	 */
	private LinkedList<Command> itsCommands = new LinkedList<>();
	
	/**
	 * 添加命令.
	 * @param c 命令.
	 */
	public void addCommand(Command c) {
		this.itsCommands.add(c);
	}
	
	/**
	 * 运行.
	 */
	public void run() {
		while (!itsCommands.isEmpty()) {
			Command c = itsCommands.getFirst();
			itsCommands.removeFirst();
			System.out.println("--->Command.execute()");
			c.execute();
		}
	}
}

Command.java

public interface Command {

	public void execute();
	
}

SleepCommandTest.java

import org.junit.Assert;
import org.junit.Test;


public class SleepCommandTest {

	private boolean commandExecuted = false;
	
	@Test
	public void testSleep() {
		Command wakeupCommand = new Command() {
			
			@Override
			public void execute() {
				commandExecuted = true;
				System.out.println("WakeUp...");
			}
		};
		
		ActiveObjectEngine engine = new ActiveObjectEngine();
		SleepCommand sleepCommand = new SleepCommand(wakeupCommand, engine, 1000);
		engine.addCommand(sleepCommand);
		long start = System.currentTimeMillis();
		engine.run();
		long stop = System.currentTimeMillis();
		long sleepTime = (stop - start);
		Assert.assertTrue("SleepTime " + sleepTime + " expected > 900", sleepTime > 900);
		Assert.assertTrue("SleepTime " + sleepTime + " expected < 1100", sleepTime < 1100);
		Assert.assertTrue("Command Executed", commandExecuted);
	}
}

SleepCommand.java

public class SleepCommand implements Command {

	/**
	 * 唤醒命令.
	 */
	private Command wakeupCommand = null;
	/**
	 * 引擎.
	 */
	private ActiveObjectEngine engine = null;
	/**
	 * 休眠时间.
	 */
	private long sleepTime = 0l;
	/**
	 * 开始时间.
	 */
	private long startTime = 0l;
	/**
	 * 是否已开始.
	 */
	private boolean started = false;
	
	/**
	 * 构造器.
	 */
	public SleepCommand(final Command wakeupCommand, final ActiveObjectEngine engine, final long milliseconds) {
		super();
		this.wakeupCommand = wakeupCommand;
		this.engine = engine;
		this.sleepTime = milliseconds;
	}
	
	/**
	 * 执行.
	 */
	@Override
	public void execute() {
		long currentTime = System.currentTimeMillis();
		if (!started) {
			started = true;
			startTime = currentTime;
			engine.addCommand(this);
		} else if ((currentTime - startTime) < sleepTime) {
			engine.addCommand(this);
		} else {
			engine.addCommand(wakeupCommand);
		}
	}

}

        和等待一个事件的多线程程序类比。当多线程程序中的一个线程等待一个事件时,它通常使用一些操作系统调用来阻塞自己直到事件发生。这里并没有阻塞,如果所等待的((currentTime - startTime) < sleepTime) 这个事件没有发生,它只是把自己放回到ActiveObjectEngine 中。

        采用该技术的变体去构建多线程系统已经是一个很常见的实践。这种类型的线程被称为run-to-completion 任务(RTC),因为每个Command 实例在下一个Command 实例可以运行之前就运行完成了。RTC 意味着Command 实例不会阻塞。

DelayedCommand.java

public class DelayedCommand implements Command {

	/**
	 * 延迟毫秒数.
	 */
	private long itsDelay;
	/**
	 * 字符.
	 */
	private char itsChar;
	/**
	 * 引擎.
	 */
	private static ActiveObjectEngine engine = new ActiveObjectEngine();
	/**
	 * 是否停用.
	 */
	private static boolean stop = false;
	
	public static void main(String[] args) {
		engine.addCommand(new DelayedCommand(100, '1'));
		engine.addCommand(new DelayedCommand(300, '3'));
		engine.addCommand(new DelayedCommand(500, '5'));
		engine.addCommand(new DelayedCommand(700, '7'));
		
		Command stopCommand = new Command() {
			@Override
			public void execute() {
				DelayedCommand.stop = true;
			}
		};
		engine.addCommand(new SleepCommand(stopCommand, engine, 2000));
		engine.run();
	}
	
	/**
	 * 构造器.
	 */
	public DelayedCommand(long delay, char c) {
		super();
		itsDelay = delay;
		itsChar = c;
	}

	/**
	 * 执行.
	 */
	@Override
	public void execute() {
		System.out.print(itsChar);
		if (!stop) {
			delayAndRepeat();
		}
	}

	private void delayAndRepeat() {
		engine.addCommand(new SleepCommand(this, engine, itsDelay));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值