模式定义:
命令模式将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式支持可撤销的操作。
命令模式可以对发送者额接受者完全解耦,发送者也接收者之间并没有直接的联系,发送者只需要知道如何发送请求,不需要关心请求是如何完成了。这就是命令模式,命令模式将方法调用给封装起来了。
模式结构:
模式实现:
public class OrderMode {
/**
* 命令接口
*/
interface Command {
void execute();
}
/**
* lol之小鱼人
*/
class Fish {
public void q() {
System.out.println("淘气打击");
}
public void w() {
System.out.println("海石三叉戟");
}
public void e() {
System.out.println("古灵精怪");
}
public void r() {
System.out.println("巨鲨强袭");
}
}
/**
* 默认命令
*/
class NoCommand implements Command {
@Override
public void execute() {
System.out.println("no command");
}
}
/**
* 技能q
*/
class Q implements Command {
private Fish fish;
public Q(Fish fish) {
this.fish = fish;
}
@Override
public void execute() {
fish.q();
}
}
/**
* 技能w
*/
class W implements Command {
private Fish fish;
public W(Fish fish) {
this.fish = fish;
}
@Override
public void execute() {
fish.w();
}
}
/**
* 技能e
*/
class E implements Command {
private Fish fish;
public E(Fish fish) {
this.fish = fish;
}
@Override
public void execute() {
fish.e();
}
}
/**
* 大招R
*/
class R implements Command {
private Fish fish;
public R(Fish fish) {
this.fish = fish;
}
@Override
public void execute() {
fish.r();
}
}
/**
* 控制器
*/
class Controller {
/**
* 栈,用于存储历史命令
*/
Stack<Command> commandStack;
/**
* 保持当前命令,方便下一次命令到达时存储
*/
Command preCommand;
public Controller() {
commandStack = new Stack<>(10);
preCommand = new NoCommand();
}
/**
* 设置命令
*
* @param command
*/
public void setCommand(Command command) {
commandStack.push(preCommand);
preCommand = command;
command.execute();
}
/**
* 回到上一个命令
*/
public void undo() {
Command command = commandStack.pop();
if (command == null) {
command = new NoCommand();
}
command.execute();
}
}
/**
* 测试类
*/
@Test
public void observerTest() {
Fish fish = new Fish();
Q q = new Q(fish);
W w = new W(fish);
E e = new E(fish);
R r = new R(fish);
Controller controller = new Controller();
controller.setCommand(q);
controller.setCommand(w);
controller.setCommand(e);
controller.setCommand(r);
controller.undo();
controller.undo();
controller.setCommand(q);
controller.undo();
controller.undo();
}
}
class Stack<T> {
/**
* 存储数据
*/
private Object[] data;
/**
* 栈顶值及元素个数
*/
private int top = 0;
/**
* 栈大小
*/
private int size;
public Stack(int size) {
this.size = size;
data = new Object[size];
top = 0;
}
/**
* 压栈
*
* @param t
*/
public synchronized void push(T t) {
if (top >= size) {
System.arraycopy(data, 1, data, 0, --top);
}
data[top++] = t;
}
/**
* 出栈
*
* @return
*/
public synchronized T pop() {
if (top <= 0) {
return null;
}
T t = (T) data[--top];
return t;
}
/**
* 获取元素数
*
* @return
*/
public int getSize() {
return top < 0 ? 0 : top;
}
}
模式优点:
1、降低了系统耦合度
2、新的命令可以很容易添加到系统中去
3、命令模式支持撤销
模式缺点:
1、使用命令模式可能会导致某些系统有过多的具体命令类
适用场景:
1、系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互
2、系统需要在不同的时间指定请求、将请求排队和执行请求
3、系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作
4、系统需要将一组操作组合在一起,即支持宏命令