1 说明
在《设计模式-行为型设计模式》文章中的4.9章节(https://blog.csdn.net/weixin_37624828/article/details/106059837)已经提到命令模式是如何编写的,并拿股票交易场景编写了一个例子,最近在看书的过程中对命令模式又有了新的认识,这次就再聊一聊命令模式以及应用。
命令模式与众多设计模式相比是很简单的,整体实现思想就是定义一个接口并定义这个接口的诸多实现,然后将其放入一个集合中,执行该集合。调用者并不关心执行的内容是什么,因为集合中的元素都实现了相同的接口。
本文介绍一种使用主动对象模式与命令模式相结合的方式实现一个多线程的程序。
2 例子
代码清单:
- Command.java --接口
- SleepCommand.java
- ActiveObjectEngine.java
- DelayedTyper.java
1 Command.java
public interface Command {
void execute();
}
2 SleepCommand.java
public class SleepCommand implements Command {
private Command wakeupCommand = null;
private ActiveObjectEngine engine = null;
private long sleepTime = 0;
private long startTime = 0;
private boolean started = false;
public SleepCommand(long milliseconds, ActiveObjectEngine e, Command wakeupCommand) {
sleepTime = milliseconds;
engine = e;
this.wakeupCommand = wakeupCommand;
}
@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);
}
}
}
3 ActiveObjectEngine.java
public class ActiveObjectEngine {
private boolean stop = false;
LinkedList itsCommands = new LinkedList();
public void addCommand(Command c) {
itsCommands.add(c);
}
public void run() {
while (!itsCommands.isEmpty()) {
Command c = (Command) itsCommands.getFirst();
itsCommands.removeFirst();
c.execute();
}
}
public void stop(){
this.stop = true;
}
}
4 DelayedTyper.java
public class DelayedTyper implements Command {
private long itsDelay;
private char itsChar;
private static ActiveObjectEngine engine = new ActiveObjectEngine();
private static boolean stop = false;
public DelayedTyper(long delay, char c) {
itsDelay = delay;
itsChar = c;
}
@Override
public void execute() {
System.out.print(itsChar);
if (!stop) {
delayAndRepeat();
}
}
private void delayAndRepeat() {
engine.addCommand(new SleepCommand(itsDelay, engine, this));
}
public static void main(String args[]) throws Exception {
engine.addCommand(new DelayedTyper(100, '1'));
engine.addCommand(new DelayedTyper(300, '3'));
engine.addCommand(new DelayedTyper(500, '5'));
engine.addCommand(new DelayedTyper(700, '7'));
Command stopCommand = new Command() {
@Override
public void execute() {
stop = false;
}
};
engine.addCommand(new SleepCommand(20000, engine, stopCommand));
engine.run();
}
}
3 运行结果
下图这些字符串之所以有差别是因为CPU时钟和实时时钟没有完美的同步。这种不可确定的行为是多线程系统的特点。
135711131511317131151131713511113151713111351113171135111315713111135117131113511137115131113157
113111351171311513111357111311513117311513111713151131135117113151131171351113111357111311513171
315111311713511131517131113151311713511113157131111351137111135111371151311311517131113511713115
131113571131113511171311513117131513111135171311151317131151131171351131115317111351131171135111
31157131113511137115131113115713111315137111135111371153111