1、引入
家电遥控器:
定义遥控器接口,使实现该类的遥控器能够控制家电。
传统OO思想:
1、创建家电的各种类。灯(包括开关功能),音响(开关机,放音乐,调音量大小)
2、直接将对象传入遥控器的实现类,不同的按钮控制不同的对象。
首先定义家电类:
//灯
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 Control {
//按下开按钮,slot是第几个按钮按下
public void onButton(int slot);
//按下关按钮
public void offButton(int slot);
//按下撤销按钮
public void undoButton();
}
//遥控器实体类
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
}
}
存在问题:
扩展性,有新的设备来了,需要增加遥控器内部的类,构造函数还要传入,case语句也要增加。违背修改的关闭,扩展的开放
遥控器与家电类强耦合,遥控器使用的是家电的具体类。开关的方法改变了,需要去改家电类的定义。(比如先关音响的音量,在关机)
2、命令模式(相当于把命令抽出来,不改变设备,只改变命令的调用)
原理:将命令抽象成一个对象,然后将对象放到遥控器中。
1、Invoker:遥控器
包含setCommand方法。能够存储命令(将命令与按钮进行关联)
2、Command(接口)
命令的抽象,包含两个功能,一个是执行(开、关、调小音量、放CD等等),一个是撤销。
3、ConcreteCommand(命令的实体类)
将执行的方法进行具体(到底是关还是开还是调小音量。。。)
将撤销进行具体(上面是开,这个就是关)
4、Receiver
家电
代码实现:
1、命令体系:
//抽象命令
public interface Command {
public void execute();
public void 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();
}
}
//开音响命令,注意此处,一个开,包含音响的两个动作
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();
}
}
//宏命令。实现多命令操作
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();
}
}
}
2、遥控器类:
此处先将五个按钮创建出来(赋的值是noCommand),然后onButton,是根据具体调用时,传入的是什么命令,再按下时调用对应的方法。
撤销的方法,使用的堆栈做的。
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();
}
}
3、具体调用:
注意宏命令以及undo的操作
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);
}
}