设计模式-命令模式

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);
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值