一、命令模式
1、定义
命令模式(Command Pattern)
是对命令的封装,每一个命令都是一个操作,请求方发出请求要求执行一个操作,接收方收到请求并执行操作。属于行为型设计模式。
命令模式通过在请求与实现之间引入一个抽象命令接口,解耦了请求与实现,并且中间件是抽象的,它由不同的子类实现,因此具备扩展性。
命令模式的本质是解耦命令请求与实现。
2、结构
(1)模式的结构
主要角色如下:
- 接收者角色(Receiver):该类负责具体实施或执行一个请求。
- 命令角色(ICommand):定义需要执行的所有命令行为。
- 具体命令角色(ConcreteCommand):该类内部维护一个 Receiver,在其 execute()方法中调用 Receiver的相关方法。
- 请求者角色(Invoker):接收客户端的命令,并执行命令。
3、优缺点
优点:
- 通过引入中间件(抽象接口),解耦了命令请求与实现。
- 扩展性好,可以很容易地增加新命令。
- 可以在现有命令的基础上,增加额外功能。
缺点:
- 具体命令类可能过多。
4、使用场景
- 请求的调用者和接收者需要解耦,使得调用者和接收者不直接交互。
- 需要抽象出等待执行的行为,比如撤销或者恢复等操作。
5、在框架源码中使用
- Java中的 Runnable接口,Runnable接口相当于命令的抽象,把用户请求和CPU执行进行解耦。
- JUnit源码中的 junit.framework.Test类。
二、模式的通用实现
代码如下:
public class CommandPattern {
public static void main(String[] args) {
ICommand commandA = new ConcreteCommandA();
Invoker invoker = new Invoker(commandA);
invoker.action();
}
}
// 接收者角色
class Receiver {
public void action() {
System.out.println("接受到指令,执行具体操作");
}
}
// 命令角色
interface ICommand {
void execute();
}
// 具体命令角色
class ConcreteCommandA implements ICommand {
private Receiver receiver = new Receiver();
@Override
public void execute() {
this.receiver.action();
}
}
// 请求者角色
class Invoker {
private ICommand cmd;
public Invoker(ICommand cmd) {
this.cmd = cmd;
}
public void action() {
this.cmd.execute();
}
}
三、模式的应用实例
以播放器的简单操作功能为例。
(1)接收者角色
public class GPlayer {
public void play(){
System.out.println("正常播放");
}
public void speed(){
System.out.println("拖动进度条");
}
public void stop(){
System.out.println("停止播放");
}
public void pause(){
System.out.println("暂停播放");
}
}
(2)命令角色
public interface IAction {
void execute();
}
(3)具体命令角色
public class PlayAction implements IAction{
private GPlayer gPlayer;
public PlayAction(GPlayer gPlayer) {
this.gPlayer = gPlayer;
}
@Override
public void execute() {
this.gPlayer.play();
}
}
public class SpeedAction implements IAction{
private GPlayer gPlayer;
public SpeedAction(GPlayer gPlayer) {
this.gPlayer = gPlayer;
}
@Override
public void execute() {
this.gPlayer.speed();
}
}
public class StopAction implements IAction{
private GPlayer gPlayer;
public StopAction(GPlayer gPlayer) {
this.gPlayer = gPlayer;
}
@Override
public void execute() {
this.gPlayer.stop();
}
}
public class PauseAction implements IAction{
private GPlayer gPlayer;
public PauseAction(GPlayer gPlayer) {
this.gPlayer = gPlayer;
}
@Override
public void execute() {
this.gPlayer.pause();
}
}
(4)请求者角色
public class InvokerController{
private List<IAction> actionList = new ArrayList<>();
public void addAction(IAction action) {
actionList.add(action);
}
public void executes(){
for (IAction action : actionList) {
action.execute();
}
actionList.clear();
}
public void execute(IAction action){
action.execute();
}
}
(5)测试
public static void main(String[] args) {
GPlayer gPlayer = new GPlayer();
InvokerController invokerController = new InvokerController();
invokerController.execute(new PlayAction(gPlayer));
System.out.println("------------------");
invokerController.addAction(new PlayAction(gPlayer));
invokerController.addAction(new SpeedAction(gPlayer));
invokerController.addAction(new StopAction(gPlayer));
invokerController.addAction(new PauseAction(gPlayer));
invokerController.executes();
}
– 求知若饥,虚心若愚。