定义
将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也可支持撤销的操作
使用场景
日志安排、线程池、队列请求、业务出现异常时的根据日志重新请求
基本框架
遥控器(调用者) <——-Command(具体命令)<——– Light(请求的接受者)
案例引入
制作一个控制器,有七个插槽,每个插槽有两个按钮的开、关按钮,并有整体的一个撤销按钮(撤销上一个操作)
简例
只一个厨房灯插槽的一个按钮(开灯按钮)
public class Light {
public void turnOn(){
System.out.println("打开灯");
}
}
public interface Command {
public void excute();
}
public class LightOnCommand implements Command {
//请求的接受者
private Light light;
public LightOnCommand(Light l){
this.light = l;
}
@Override
public void excute() {
light.turnOn();
}
}
public class SimpleRemoteControl {
//注入具体命令(将开灯请求封装成开灯命令),该命令中具体的请求执行者
private Command command;
public SimpleRemoteControl(Command command){
this.command = command;
}
public void setCommand(Command command){
this.command = command;
}
//遥控器的按钮操作
public void pressButton(){
command.excute();
}
}
public class RemoteControlTest {
public static void main(String[] args) {
Light light = new Light();
Command command = new LightOnCommand(light);
SimpleRemoteControl remoteControl = new SimpleRemoteControl(command);
remoteControl.pressButton();
}
}
遥控器7个插槽、再加上撤销按钮
public class Light {
public void turnOn(){
System.out.println("打开灯");
}
public void turnOff(){
System.out.println("关灯");
}
}
public class LightOffCommand implements Command {
//请求的接受者
private Light light;
public LightOffCommand(Light l){
this.light = l;
}
@Override
public void excute() {
light.turnOff();
}
}
public class RemoteControl {
// 这两个数组来盛放7个插槽的开、关命令
private Command[] onCommands;
private Command[] offCommands;
// 标记上一个撤销命令
private Command undoCommand;
public RemoteControl(){
this.onCommands = new Command[7];
this.offCommands = new Command[7];
Command noCommand = new NoCommand();
for (int i = 0; i < 7; i++) {
//设置一个空命令
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
undoCommand = noCommand;
}
public void setCommands(int slot,Command onCommand,Command offCommand){
onCommands[slot] = onCommand;
offCommands[slot] = onCommand;
}
public void pressOnButton(int slot){
onCommands[slot].excute();
undoCommand = onCommands[slot];
}
public void pressOffButton(int slot){
offCommands[slot].excute();
undoCommand = offCommands[slot];
}
//撤销
public void undoCommand(){
undoCommand.excute();
}
}
public class RemoteControlTest {
public static void main(String[] args) {
Light light = new Light();
TV tv = new TV();
Command lightOnCommand = new LightOnCommand(light);
Command lightOffCommand = new LightOffCommand(light);
Command tvOnCommand = new TVOnCommand(tv);
Command tvOffCommand = new TVOffCommand(tv);
RemoteControl remoteControl = new RemoteControl();
remoteControl.setCommands(0, lightOnCommand, lightOffCommand);
remoteControl.setCommands(1, tvOnCommand, tvOffCommand);
remoteControl.pressOnButton(0);
remoteControl.pressOffButton(0);
System.out.println("==============");
remoteControl.pressOnButton(1);
remoteControl.pressOffButton(1);
System.out.println("==============");
//执行撤销操作
remoreControl.undoComand();
}
}
实现多层次的撤销操
将每次的命令操作都放在栈里,撤销的时候,从栈里取出最上层的命令
public class RemoteControl {
// 这两个数组来盛放7个插槽的开、关命令
private Command[] onCommands;
private Command[] offCommands;
// 定义一个栈 来保存每次的命令
private Stack<Command> undoCommandStack;
public RemoteControl(){
this.onCommands = new Command[7];
this.offCommands = new Command[7];
Command noCommand = new NoCommand();
for (int i = 0; i < 7; i++) {
//设置一个空命令
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
//undoCommand = noCommand;
}
public void setCommands(int slot,Command onCommand,Command offCommand){
onCommands[slot] = onCommand;
offCommands[slot] = onCommand;
}
public void pressOnButton(int slot){
onCommands[slot].excute();
//undoCommand = onCommands[slot];
undoCommandStack.add(onCommands[slot]);
}
public void pressOffButton(int slot){
offCommands[slot].excute();
//undoCommand = offCommands[slot];
undoCommandStack.add(offCommands[slot]);
}
//撤销
public void undoCommand(){
//undoCommand.excute();
if(!undoCommandStack.empty()){
Command undoCommand = undoCommandStack.pop();
undoCommand.excute();
}else{
syso("已经撤销了所有命令!");
}
}
}
用party模式完善上述案例 ###
你想坐在沙发上吃着薯片舒适的看电视,但仅凭一个遥控器无法同时弄暗灯光、打开音响、电视等,还必须分别调好,遥控器也就失去了意义。
将这一系列的命令封装起来,做成一个遥控器------即 party模式
public class MacroCommand implements Command{
private Command[] commands;
public MacroCommand(Command[] commands){
this.commands = commands;
}
@override
public void excute(){
for(int i =0; i< commands.lenght; i++){
commands[1].excute();
}
}
}
应用场景
工作队列
线程池或者其他工作队列,可以在一个线程同步或者多个线程一部执行工作队列.(web服务器是怎样处理这种的队列方式? )