敏捷软件开发(3)---COMMAND 模式 & Active Object 模式

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 

原文地址:https://www.cnblogs.com/deman/p/5553538.html