一.定义
命令模式:将一个请求封装为一个命令对象,从而使你可用不同的请求对客户端进行参数化,对请求排队,组合,存储等,以及支持可撤销的操作;一.类结构图
一.举例
场景:模拟开灯,关灯,开,关音响,调音量命令命令接受者:Lignt.java;Stereo.java
public class Light {
String loc = "";
public Light(String loc) {
this.loc = loc;
}
public void On() {
System.out.println(loc + " On");
}
public void Off() {
System.out.println(loc + " Off");
}
}
public class Stereo {
static int volume = 0;
public void On() {
System.out.println("Stereo On");
}
public void Off() {
System.out.println("Stereo Off");
}
public void SetCd() {
System.out.println("Stereo SetCd");
}
public void SetVol(int vol) {
volume = vol;
System.out.println("Stereo volume=" + volume);
}
public int GetVol() {
return volume;
}
public void Start() {
System.out.println("Stereo Start");
}
}
命令接口:
public interface Command {
public void execute();
public void undo();
}
如下封装命令对象:
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light)
{
this.light=light;
}
@Override
public void execute() {
// TODO Auto-generated method stub
light.Off();
}
@Override
public void undo() {
// TODO Auto-generated method stub
light.On();
}
}
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light)
{
this.light=light;
}
@Override
public void execute() {
// TODO Auto-generated method stub
light.On();
}
@Override
public void undo() {
// TODO Auto-generated method stub
light.Off();
}
}
public class StereoAddVolCommand implements Command {
private Stereo setreo;
public StereoAddVolCommand(Stereo setreo)
{
this.setreo=setreo;
}
@Override
public void execute() {
// TODO Auto-generated method stub
int vol= setreo.GetVol();
if(vol<11)
{
setreo.SetVol(++vol);
}
}
@Override
public void undo() {
// TODO Auto-generated method stub
int vol= setreo.GetVol();
if(vol>0)
{
setreo.SetVol(--vol);
}
}
.....剩余命令对象略
下面是Invoker对象
public class CommandModeControl implements Control{
private Command[] onCommands;
private Command[] offCommands;
private Stack<Command> stack=new Stack<Command>();
public CommandModeControl()
{
onCommands=new Command[5];
offCommands=new Command[5];
Command noCommand=new NoCommand();
for(int i=0,len=onCommands.length;i<len;i++)
{
onCommands[i]=noCommand;
offCommands[i]=noCommand;
}
}
public void setCommand(int slot,Command onCommand,Command offCommand)
{
onCommands[slot]=onCommand;
offCommands[slot]=offCommand;
}
@Override
public void onButton(int slot) {
onCommands[slot].execute();
stack.push(onCommands[slot]);
}
@Override
public void offButton(int slot) {
offCommands[slot].execute();
stack.push(offCommands[slot]);
}
@Override
public void undoButton() {
// TODO Auto-generated method stub
stack.pop().undo();
}
Client 客户端
public static void main(String[] args) {
CommandModeControl control = new CommandModeControl();
MarcoCommand onmarco,offmarco;
Light bedroomlight = new Light("BedRoom");
Light kitchlight = new Light("Kitch");
Stereo stereo = new Stereo();
LightOnCommand bedroomlighton = new LightOnCommand(bedroomlight);
LightOffCommand bedroomlightoff = new LightOffCommand(bedroomlight);
LightOnCommand kitchlighton = new LightOnCommand(kitchlight);
LightOffCommand kitchlightoff = new LightOffCommand(kitchlight);
Command[] oncommands={bedroomlighton,kitchlighton};
Command[] offcommands={bedroomlightoff,kitchlightoff};
onmarco=new MarcoCommand(oncommands);
offmarco=new MarcoCommand(offcommands);
StereoOnCommand stereoOn = new StereoOnCommand(stereo);
StereoOffCommand stereoOff = new StereoOffCommand(stereo);
StereoAddVolCommand stereoaddvol = new StereoAddVolCommand(stereo);
StereoSubVolCommand stereosubvol = new StereoSubVolCommand(stereo);
control.setCommand(0, bedroomlighton, bedroomlightoff);
control.setCommand(1, kitchlighton, kitchlightoff);
control.setCommand(2, stereoOn, stereoOff);
control.setCommand(3, stereoaddvol, stereosubvol);
control.setCommand(4, onmarco, offmarco);
control.onButton(0);
control.undoButton();
//control.offButton(0);
control.onButton(1);
control.offButton(1);
control.onButton(2);
control.onButton(3);
control.offButton(3);
control.undoButton();
control.offButton(2);
control.undoButton();
control.onButton(4);
control.offButton(4);
}
命令模式的优势:
命令对象的本质你将命令封装成对象,将发出命令和执行命令的责任分开;这带来的好处有:我们可以对命令进行组合,设计成一个队列;对命令进行存储,放入一个栈结构中,这样就支持回退操作,还可以将命令记录日志;可以很容易的加入新的命令而不影响其他的类。