COMMAND 模式 command模式非常簡單,簡單到你無法想象的地方。 這就是一個command模式的樣子。也許你會覺得,這有點多此一舉嗎。但是當你使用他的時候,command模式就會閃現光華。 這樣一個場景:經理張三叫leader王二去開發一個項目, 王二就安排李四 去開發這個功能A。 李四何 ...
COMMAND 模式
command模式非常簡單,簡單到你無法想象的地方。
public interface Command { void execute(); }
這就是一個command模式的樣子。也許你會覺得,這有點多此一舉嗎。但是當你使用他的時候,command模式就會閃現光華。
這樣一個場景:經理張三叫leader王二去開發一個項目, 王二就安排李四 去開發這個功能A。 李四何時執行,怎麼執行就是他自己的事情了。
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