《Head First 设计模式》学习笔记——命令模式

在软件系统,“行为请求者”与“行为实施者”通常存在一个“紧耦合”。但在某些场合,比方要对行为进行“记录、撤销/重做、事务”等处理,这样的无法抵御变化的紧耦合是不合适的。在这样的情况下。怎样将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象实现二者之间的松耦合。这就是命令模式(Command Pattern)————题记

设计模式
命令模式:将“请求”封装成对象,以便使用不同的请求、队列或者日志来參数化其它对象。

命令模式也支持可撤销的操作。


模式分析
1. 命令模式的本质是对命令进行封装,将发出命令的责任和运行命令的责任切割开
2. 每个命令都是一个操作:请求的一方发出请求,要求运行一个操作;接收的一方收到请求,并运行操作
3. 命令模式同意请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被运行、何时被运行,以及是怎么被运行的。
4. 命令模式使请求本身成为一个对象,这个对象和其它对象一样能够被存储和传递。
5. 命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,仅仅有实现了抽象命令接口的详细命令才干与接收者相关联

// Invoker:要求命令对象运行请求,一般会持有命令对象,能够持有非常多的命令对象。这个是client真正触发命令并要求命令运行对应操作的地方,也就是说相当于使用命令对象的入口。
public class RemoteControl {
	//这时候。遥控器要处理7个开与关的命令,使用对应数组记录这些命令
	Command[] onCommands;
	Command[] offCommands;
 
	public RemoteControl() {
		//在构造器中。仅仅须要实例化并初始化两个开与关的数组
		onCommands = new Command[7];
		offCommands = new Command[7];
		//NoCommand对象是一个空对象(null obeject)的样例。当你不想返回一个有意义的对象时,空对象就非常实用,客户也能够将处理null的责任转义给空对象。

//举例来说。遥控器不可能一出厂就设置了有意义的命令对象,所以提供了NoCommand对象作为替代品。当调用它的execute() //方法时。这样的对象什么也不做。 Command noCommand = new NoCommand(); for (int i = 0; i < 7; i++) { onCommands[i] = noCommand; offCommands[i] = noCommand; } } //setCommand()方法须有三个參数,各自是插槽的位置、开的命令、关的命令。 public void setCommand(int slot, Command onCommand, Command offCommand) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } //当按下开或关的button。硬件就会负责调用对应的方法 public void onButtonWasPushed(int slot) { onCommands[slot].execute(); } public void offButtonWasPushed(int slot) { offCommands[slot].execute(); } //覆盖toString(),打印出每一个插槽和它对应的命令。 public String toString() { StringBuffer stringBuff = new StringBuffer(); stringBuff.append(" ------ Remote Control ------- "); for (int i = 0; i < onCommands.length; i++) { stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName() + " " + offCommands[i].getClass().getName() + " "); } return stringBuff.toString(); } } //定义命令的接口。声明运行的方法。 public interface Command { public void execute(); } //命令接口实现对象,是“虚”的实现。一般会持有接收者,并调用接收者的功能来完毕命令要运行的操作。 public class StereoOnWithCDCommand implements Command { Stereo stereo; public StereoOnWithCDCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { stereo.on(); stereo.setCD(); stereo.setVolume(11); } } //接收者,真正运行命令的对象。

不论什么类都可能成为一个接收者。仅仅要它能够实现命令要求实现的对应功能。 public class Stereo { String location; public Stereo(String location) { this.location = location; } public void on() { System.out.println(location + " stereo is on"); } public void off() { System.out.println(location + " stereo is off"); } public void setCD() { System.out.println(location + " stereo is set for CD input"); } public void setDVD() { System.out.println(location + " stereo is set for DVD input"); } public void setRadio() { System.out.println(location + " stereo is set for Radio"); } public void setVolume(int volume) { // code to set the volume // valid range: 1-11 (after all 11 is better than 10, right?) System.out.println(location + " Stereo volume set to " + volume); } } //測试 public class RemoteLoader { public static void main(String[] args) { RemoteControl remoteControl = new RemoteControl(); //将所有的装置创建在合适的位置 Light livingRoomLight = new Light("Living Room"); Light kitchenLight = new Light("Kitchen"); CeilingFan ceilingFan= new CeilingFan("Living Room"); GarageDoor garageDoor = new GarageDoor(""); Stereo stereo = new Stereo("Living Room"); LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight); LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight); LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight); LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight); CeilingFanOnCommand ceilingFanOn = new CeilingFanOnCommand(ceilingFan); CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan); GarageDoorUpCommand garageDoorUp = new GarageDoorUpCommand(garageDoor); GarageDoorDownCommand garageDoorDown = new GarageDoorDownCommand(garageDoor); StereoOnWithCDCommand stereoOnWithCD = new StereoOnWithCDCommand(stereo); StereoOffCommand stereoOff = new StereoOffCommand(stereo); //如今已经有了所有的命令。能够将他们载入到遥控器插槽中。 remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff); remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff); remoteControl.setCommand(2, ceilingFanOn, ceilingFanOff); remoteControl.setCommand(3, stereoOnWithCD, stereoOff); //在这里,使用toString()方法打印出每一个遥控器的插槽和它被指定的命令 System.out.println(remoteControl); //一切就绪,逐步按下每一个插槽的开与关button。

remoteControl.onButtonWasPushed(0); remoteControl.offButtonWasPushed(0); remoteControl.onButtonWasPushed(1); remoteControl.offButtonWasPushed(1); remoteControl.onButtonWasPushed(2); remoteControl.offButtonWasPushed(2); remoteControl.onButtonWasPushed(3); remoteControl.offButtonWasPushed(3); } }




版权声明:本文博主原创文章,博客,未经同意不得转载。

原文地址:https://www.cnblogs.com/gcczhongduan/p/4878240.html