一、简介
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
JDK的java.util.concurrent包的ThreadPoolExecutor类就用到命令模式。
二、简易命令模式组成
1.Command(抽象命令类): 声明了用于执行请求的的exceute()
等方法
2.ConcreteCommand(具体命令类): 抽象命令类
的子类,对应具体的接收者对象,将接收者对象的动作绑定其中。在实现execute()方法时,将调用接收者对象的相关操作(Action)。
3.Invoker(调用者): 调用命令对象执行请求,它持有了一个命令队列,客户端代码可以向它提交要执行的任务(命令)。
4.Receiver(接收者): 真正的命令执行对象。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
三、简易命令模式UML图
四、ThreadPoolExecutor类对命令模式的实现
1.抽象命令Command:Runnable接口
2.具体命令类ConcreteCommand:由需要使用线程的开发者自己创建这个类,实现Runnable接口,重写run方法,在run方法中写具体的业务逻辑。不搞Receiver。
3.调用者Invoker:ThreadPoolExecutor 它持有了一个命令队列,客户端代码可以向它提交要执行的任务(命令)。
4.命令队列:BlockingQueue 任务阻塞队列,它实际上就是模式中的“命令队列”;
5.Receiver:被调用者,也就是具体做事情的人。通常写多线程代码的时候,开发者会将Runnable实现类(具体命令类ConcreteCommand)直接在重写的run方法中实现具体的逻辑,而不使用Receiver。设计模式重点在于结合场景并不是教条,不用纠结于此。
五、例子:使用ThreadPoolExecutor线程池启动一个线程
UML图
代码
1.抽象命令Runnable接口
public interface Runnable {
public abstract void run();
}
2.自己写的具体命令类ConcreteCommand实现Runnable接口
package com.sid;
/**
* @program: thread-test
* @description:
* @author: Sid
* @date: 2019-01-17 16:12
* @since: 1.0
**/
public class ConcreteCommand implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is runing");
}
}
3.调用者ThreadPoolExecutor(跟命令模式无关的代码不贴)
public class ThreadPoolExecutor {
private final BlockingQueue<Runnable> workQueue; //命令队列
public void execute(Runnable command) {/*跟命令模式无关不贴*/} //加入命令队列
final void runWorker(Worker w) {/*跟命令模式无关不贴*/}//执行命令队列中所有命令
}
4.客户端调用
package com.sid;
import java.util.concurrent.*;
/**
* @program: thread-test
* @description:
* @author: Sid
* @date: 2019-01-15 17:02
* @since: 1.0
**/
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(5,
Runtime.getRuntime().availableProcessors() * 2,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(200),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("order-thread");
return t;
}
}, new ThreadPoolExecutor.AbortPolicy());
Runnable concreteCommand = new ConcreteCommand();
pool.execute(concreteCommand);
pool.shutdown();
}
}