命令模式

一、概述

命令模式支持请求调用者与请求接收者之间的解耦。

用途:命令可以将元算块打包(一个接收者一组动作),然后将它传来传去,就像一般的对象一样。即使在命令对象创建许久之后依然可以被调用。事实上,这甚至可以在不同的线程中被调用。可以利用这些特性衍生出一些应用。schedule、线程池、工作队列等。工作队列:在某一段添加命令,然后另一端是线程,线程从队列中取出一个命令元素,然后执行命令元素的 execute() 方法,当该方法调用完毕之后则丢弃该命令元素。

二、类图

 三、代码

需要操作的对象(电灯)

package com.scott.command.undo;

public class Light {
	String location;
	int level;

	public Light(String location) {
		this.location = location;
	}

	public void on() {
		level = 100;
		System.out.println("Light is on");
	}

	public void off() {
		level = 0;
		System.out.println("Light is off");
	}
    
       /**
        * 设置电灯的亮度
        */
	public void dim(int level) {
		this.level = level;
		if (level == 0) {
			off();
		}
		else {
			System.out.println("Light is dimmed to " + level + "%");
		}
	}

	public int getLevel() {
		return level;
	}
}

命令接口

/**
 * 指令接口
 *
 * @author Scott
 */
public interface Command {
	/**
	 * 执行方法
	 */
	void execute();
}

命令的实现

package com.scott.command.undo;

public class DimmerLightOnCommand implements Command {
	Light light;
	int prevLevel;

	public DimmerLightOnCommand(Light light) {
		this.light = light;
	}

	@Override
	public void execute() {
		prevLevel = light.getLevel();
		light.dim(75);
	}

	@Override
	public void undo() {
		light.dim(prevLevel);
	}
}
package com.scott.command.undo;

public class DimmerLightOffCommand implements Command {
	Light light;
	int prevLevel;

	public DimmerLightOffCommand(Light light) {
		this.light = light;
		prevLevel = 100;
	}

	@Override
	public void execute() {
		prevLevel = light.getLevel();
		light.off();
	}

	@Override
	public void undo() {
		light.dim(prevLevel);
	}
}

命令的控制器

package com.scott.command.undo;

/**
 * 控制器
 */
public class RemoteControlWithUndo {
	Command[] onCommands;
	Command[] offCommands;
	/** 最后一次触发的命令*/
	Command undoCommand;
 
	public RemoteControlWithUndo() {
		onCommands = new Command[7];
		offCommands = new Command[7];
 
		Command noCommand = new NoCommand();
		for(int i = 0; i < 7; i++) {
			onCommands[i] = noCommand;
			offCommands[i] = noCommand;
		}
		undoCommand = noCommand;
	}
  
	public void setCommand(int slot, Command onCommand, Command offCommand) {
		onCommands[slot] = onCommand;
		offCommands[slot] = offCommand;
	}

	/**
	 * 开的命令,最后将该命令赋值给最后一个指令变量中
	 * @param slot
	 */
	public void onButtonWasPushed(int slot) {
		onCommands[slot].execute();
		undoCommand = onCommands[slot];
	}
 
	public void offButtonWasPushed(int slot) {
		offCommands[slot].execute();
		undoCommand = offCommands[slot];
	}

	/**
	 * 实现指令在执行错误或者调用完毕后的反转
	 */
	public void undoButtonWasPushed() {
		undoCommand.undo();
	}

	@Override
	public String toString() {
		StringBuffer stringBuff = new StringBuffer();
		stringBuff.append("\n------ Remote Control -------\n");
		for (int i = 0; i < onCommands.length; i++) {
			stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()
				+ "    " + offCommands[i].getClass().getName() + "\n");
		}
		stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n");
		return stringBuff.toString();
	}
}

持有器测试

package com.scott.command.undo;

public class RemoteLoader {
 
	public static void main(String[] args) {
		RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();
 
		Light livingRoomLight = new Light("Living Room");

		DimmerLightOnCommand dimmerLightOnCommand = new DimmerLightOnCommand(livingRoomLight);
		DimmerLightOffCommand dimmerLightOffCommand = new DimmerLightOffCommand(livingRoomLight);

		remoteControl.setCommand(0, dimmerLightOnCommand, dimmerLightOffCommand);
		remoteControl.onButtonWasPushed(0);
		remoteControl.offButtonWasPushed(0);
		remoteControl.undoButtonWasPushed();

	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值