命令模式將請求封裝成對象,以便使用不同的請求、隊列或者日誌來參數化其他對象。命令模式支持可撤銷的操作。
命令模式可以對發送者額接受者完全解耦,發送者也接收者之間並沒有直接的聯繫,發送者只需要知道如何發送請求,不需要關心請求是如何完成了。這就是命令模式,命令模式將方法調用給封裝起來了。
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;
}
}