传统OOP方式:
控制器
package com.java.jikexueyuan.commandmode;
/**
* 定义一个遥控器接口
*/
public interface Control {
/**
* 开
* @param slot
*/
public void onButton(int slot);
/**
* 关
* @param slot
*/
public void offButton(int slot);
/**
* 回退
*/
public void undoButton();
}
实现
package com.java.jikexueyuan.commandmode;
import com.java.jikexueyuan.commandmode.device.Light;
import com.java.jikexueyuan.commandmode.device.Stereo;
/**
* 模拟一个遥控器 可以操作传递进来的灯和收音机
* 直接设定每一个位置的功能
* *0 *3
* *1 *4
* *2 *5
*
* 虽然完成了按指定的按钮 可以进行相应的操作
* 但是 我们的控制器和我们的命令直接耦合死了。如果新增一个家电,也想要被遥控器操作,那么就需要修改我们的构造方法,成员变量。成员方法
*
*
*/
public class TraditionControl implements Control {
Light light;
Stereo stereo;
public TraditionControl(Light light, Stereo stereo) {
this.light = light;
this.stereo = stereo;
}
@Override
public void onButton(int slot) {
// TODO Auto-generated method stub
switch (slot) {
case 0:
light.On();
break;
case 1:
stereo.On();
break;
case 2:
int vol = stereo.GetVol();
if (vol < 11) {
stereo.SetVol(++vol);
}
break;
}
}
@Override
public void offButton(int slot) {
// TODO Auto-generated method stub
switch (slot) {
case 0:
light.Off();
break;
case 1:
stereo.Off();
break;
case 2:
int vol = stereo.GetVol();
if (vol > 0) {
stereo.SetVol(--vol);
}
break;
}
}
@Override
public void undoButton() {
// TODO Auto-generated method stub
}
}
家具模拟
package com.java.jikexueyuan.commandmode.device;
/**
* 模拟一个灯 可根据传递不同的参数 操作不同的灯
*/
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");
}
}
package com.java.jikexueyuan.commandmode.device;
/**
* 模拟一个收音机
* 有开关,设置cd 设置声音 获取声音的功能
*/
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");
}
}
Demo
package com.java.jikexueyuan.commandmode;
import com.java.jikexueyuan.commandmode.device.Light;
import com.java.jikexueyuan.commandmode.device.Stereo;
public class ControlTest {
public static void main(String[] args) {
Control ctl;
Light light = new Light("Bedroom");
Stereo stereo = new Stereo();
ctl = new TraditionControl(light, stereo);
ctl.onButton(0);
ctl.offButton(0);
ctl.onButton(1);
ctl.onButton(2);
ctl.offButton(2);
ctl.offButton(1);
}
}
命令模式实现:
命令接口
package com.java.jikexueyuan.commandmode.command;
/**
* 将我们的每一条命令都封装为对象,控制器不直接执行具体的命令,而是操作命令接口的方法,
* 将具体操作什么样的命令交给接口的实现类来决定 ,从而实现了我们控制器和命令的解耦合。
*/
public interface Command {
/**
* 定义执行接口
*/
public void execute();
/**
* 定义撤销接口
*/
public void undo();
}
基础命令
package com.java.jikexueyuan.commandmode.command;
import com.java.jikexueyuan.commandmode.device.Light;
/**
* * 定义关闭灯的command命令。并且构造方法中传递具体需要关闭的灯名称
* * 关闭灯所对应的回退undo 为打开灯。在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();
}
}
package com.java.jikexueyuan.commandmode.command;
import com.java.jikexueyuan.commandmode.device.Light;
/**
* 定义打开灯的command命令。并且构造方法中传递具体需要打开的灯名称
* 打开灯所对应的回退undo 为关闭灯。在undo中调用相应的回退命令方法
*
*/
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();
}
}
package com.java.jikexueyuan.commandmode.command;
import com.java.jikexueyuan.commandmode.device.Stereo;
/**
* 加声音的命令以及回退
*/
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);
}
}
}
package com.java.jikexueyuan.commandmode.command;
import com.java.jikexueyuan.commandmode.device.Stereo;
/**
* 关闭收音机命令
*/
public class StereoOffCommand implements Command {
private Stereo setreo;
public StereoOffCommand(Stereo setreo)
{
this.setreo=setreo;
}
@Override
public void execute() {
// TODO Auto-generated method stub
setreo.Off();
}
@Override
public void undo() {
// TODO Auto-generated method stub
setreo.On();
setreo.SetCd();
}
}
package com.java.jikexueyuan.commandmode.command;
import com.java.jikexueyuan.commandmode.device.Stereo;
/**
* 打开收音机的命令。在execute 执行时。可以同时进行多种操作。合并为同一命令
*/
public class StereoOnCommand implements Command {
private Stereo setreo;
public StereoOnCommand(Stereo setreo)
{
this.setreo=setreo;
}
@Override
public void execute() {
// TODO Auto-generated method stub
setreo.On();
setreo.SetCd();
}
@Override
public void undo() {
// TODO Auto-generated method stub
setreo.Off();
}
}
package com.java.jikexueyuan.commandmode.command;
import com.java.jikexueyuan.commandmode.device.Stereo;
public class StereoSubVolCommand implements Command {
private Stereo setreo;
public StereoSubVolCommand(Stereo setreo)
{
this.setreo=setreo;
}
@Override
public void execute() {
// TODO Auto-generated method stub
int vol= setreo.GetVol();
if(vol>0)
{
setreo.SetVol(--vol);
}
}
@Override
public void undo() {
// TODO Auto-generated method stub
int vol= setreo.GetVol();
if(vol<11)
{
setreo.SetVol(++vol);
}
}
}
初始化时什么都不操作的命令
package com.java.jikexueyuan.commandmode.command;
/**
* 定义一个NoCommand实现,当我们控制器的某项按钮没有指定相应的命令时,进行空实现,有需要的时候再进行设置
*/
public class NoCommand implements Command {
@Override
public void execute() {
// TODO Auto-generated method stub
}
@Override
public void undo() {
// TODO Auto-generated method stub
}
}
宏命令(批量操作命令)
package com.java.jikexueyuan.commandmode.command;
/**
* 宏命令 自定义一组命令集合,可同时执行,例如,同时打开卧室灯,厨房灯。 同时关闭等等
* 控制器在进行操作时 并不在乎我们所传递的为宏命令还是单一命令。他都会逐个的进行操作
*/
public class MarcoCommand implements Command {
private Command[] commands;
public MarcoCommand(Command[] commands) {
this.commands = commands;
}
@Override
public void execute() {
// TODO Auto-generated method stub
for (int i = 0, len = commands.length; i < len; i++) {
commands[i].execute();
}
}
@Override
public void undo() {
// TODO Auto-generated method stub
for (int i = commands.length - 1; i >= 0; i--) {
commands[i].undo();
}
}
}
控制器实现
package com.java.jikexueyuan.commandmode.command;
import java.util.Stack;
import com.java.jikexueyuan.commandmode.Control;
import com.java.jikexueyuan.commandmode.device.Light;
import com.java.jikexueyuan.commandmode.device.Stereo;
/**
* 定义控制器
* *on *off
* *1 *1
* *2 *2
* *2 *2
* *2 *2
* *2 *2
*
*/
public class CommandModeControl implements Control {
private Command[] onCommands;
private Command[] offCommands;
/**
* 创建命令栈
*/
private Stack<Command> stack = new Stack<Command>();
/**
* 构造方法中初始化控制器的命令。将所有的命令设置为noCommand (即按了没反应)
* 初始化五个onCommand 五个offCommand
*/
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;
}
}
/**
* 给指定的一排按钮添加响应的on命令 off命令
* @param slot
* @param onCommand
* @param offCommand
*/
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
/**
* 执行指定行上的开按钮 并且通过栈记录相应的操作
* @param slot
*/
@Override
public void onButton(int slot) {
onCommands[slot].execute();
stack.push(onCommands[slot]);
}
/**
* 执行指定行上的关按钮 并且通过栈记录相应的操作
* @param 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();
}
}
Demo
package com.java.jikexueyuan.commandmode.command;
import com.java.jikexueyuan.commandmode.Control;
import com.java.jikexueyuan.commandmode.TraditionControl;
import com.java.jikexueyuan.commandmode.device.Light;
import com.java.jikexueyuan.commandmode.device.Stereo;
public class ControlTest {
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);
}
/**
* 命令模式:将请求、命令、动作等封装成对象,这样可以让项目使用这些对象来
* 参数化其他对象。使得命令的请求者和执行者解耦
*
*
*/
}