COMMAND 模式
command模式非常简单,简单到你无法想象的地方。
public interface Command { void execute(); }
这就是一个command模式的样子。也许你会觉得,这有点多此一举吗。但是当你使用他的时候,command模式就会闪现光华。
这样一个场景:经理张三叫leader王二去开发一个项目, 王二就安排李四 去开发这个功能A。 李四何时执行,怎么执行就是他自己的事情了。
![](http://upload-images.jianshu.io/upload_images/2187677-5fb9b3c5b465e8c6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
UML图如上所示:
代码如下:
public interface CommandInterface { void execute(); }
public class ContractCommand implements CommandInterface { Member member; public ContractCommand(Member member) { this.member = member; } @Override public void execute() { member.action(); } }
public class Member { public void action() { TraceLog.i(); } }
Leader,获取命令,然后执行命令。
public class Leader { CommandInterface commandInterface; public void setCommandInterface(CommandInterface commandInterface) { this.commandInterface = commandInterface; } public void executeCommand() { commandInterface.execute(); } }
public class Manager { public static void main() { Member m = new Member(); CommandInterface c = new ContractCommand(m); Leader wang2 = new Leader(); wang2.setCommandInterface(c); wang2.executeCommand(); } }
manager创建运行的平台。
这样命令模式就开启了。
Active Object
Active Object 模式
一开始蛮难理解这个模式的目的,而且GOF的23中经典模式里也没有这个模式。
/** * @author deman.lu * @version on 2016-06-02 14:45 */ public class ActiveObjectEngine { List<CommandInterface> itsCommands = new ArrayList(); /*need to running in main thread, should check with synchronized*/ public void addCommand(CommandInterface aCommand) { itsCommands.add(aCommand); } public void run() { /*should running in background*/ while (itsCommands.size() > 0) { CommandInterface c = itsCommands.get(0); itsCommands.remove(0); c.execute(); } } }
这个就是ActiveObject的engine,2个函数。一个是把一条command添加到表里面。
另一个是一个循环,处理问题。仔细思考,这就是消费者,和生产者问题的变种。
but这里没有线程block的地方。先看完全部代码:
public class SleepCommand implements CommandInterface { @Override public void execute() { Date currentTime = new Date(); if (!started) { started = true; this.startTime = currentTime; this.engine.addCommand(this); } else { long elapsedTime = currentTime.getTime() - startTime.getTime(); if (elapsedTime < SleepTime) { this.engine.addCommand(this); } else { this.engine.addCommand(this.wakeupCommand); } } } private CommandInterface wakeupCommand = null; private ActiveObjectEngine engine = null; private long SleepTime = 0; private Date startTime; private boolean started = false; public SleepCommand(long milliSeconds, ActiveObjectEngine e, CommandInterface wakeupCommand) { this.SleepTime = milliSeconds; this.engine = e; this.wakeupCommand = wakeupCommand; } }
public class DelayedTyper implements CommandInterface { private long itsDelay; private char itsChar; private static boolean stop = false; static String printStr = ""; private static ActiveObjectEngine engin = new ActiveObjectEngine(); static class StopCommand implements CommandInterface { @Override public void execute() { DelayedTyper.stop = true; } } public static void Main() { engin.addCommand(new DelayedTyper(100, 'A')); engin.addCommand(new DelayedTyper(300, 'B')); engin.addCommand(new DelayedTyper(500, 'C')); engin.addCommand(new DelayedTyper(700, 'D')); CommandInterface stopCommand = new StopCommand(); engin.addCommand(new SleepCommand(2000, engin, stopCommand)); engin.run(); TraceLog.i(printStr); } public DelayedTyper(long delay, char c) { this.itsDelay = delay; this.itsChar = c; } @Override public void execute() { printStr +=itsChar; if (!stop) { DelayAndRepeat(); } } private void DelayAndRepeat() { engin.addCommand(new SleepCommand(itsDelay, engin, this)); } }
结果如下:
ABCDAAABACABAADAABCAAABAADABCAAABAACDB
当DelayedTyper没有到执行的时间点的时候,启动SleepCommand。
这个很关键,
if (elapsedTime < SleepTime) { this.engine.addCommand(this); } else { this.engine.addCommand(this.wakeupCommand); }
如果时间没到,就把自己加入到队列最后,等待下次执行。(此处没有用常见的线程block技术)
时间到了,就把wakeupCommand加入执行队列。
这里还有个关键是,没有stopcommand,命令会一直循环执行。
参考:
《敏捷软件开发》 Robert C. Martin