敏捷軟件開發(3)---COMMAND 模式 & Active Object 模式

COMMAND 模式

command模式很是簡單,簡單到你沒法想象的地方。ide

public interface Command {
    void execute();
}

這就是一個command模式的樣子。也許你會以爲,這有點畫蛇添足嗎。可是當你使用他的時候,command模式就會閃現光華。函數

這樣一個場景:經理張三叫leader王二去開發一個項目, 王二就安排李四 去開發這個功能A。 李四什麼時候執行,怎麼執行就是他本身的事情了。this


 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,獲取命令,而後執行命令。spa

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建立運行的平臺。線程

這樣命令模式就開啓了。code

Active Object

Active Object 模式blog

一開始蠻難理解這個模式的目的,並且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添加到表裏面。ip

另外一個是一個循環,處理問題。仔細思考,這就是消費者,和生產者問題的變種。開發

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 

相關文章
相關標籤/搜索