菜鸟柳--23种设计模式初学记录笔记(五)命令模式

首先是简单版本的设计模式:

命令模式:将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。

案例:

某个公司需要设计一个多用功能的遥控器。基本的需求如下:

该遥控器有可以控制风扇,白炽灯,热水器等等的多对开关,而且可能还有其他的电器,暂时不做其功能,但是希望可以保留接口,用的时间可以方便的扩展。

除上面的需求之外,还需要有个按钮,可以撤销上一步的操作。基本功能如下图:


在设计遥控器时,风扇,白炽灯,热水器的开关方法已经定义好,其名字各不相同。不妨设置其方法为如下:单拿灯做例子

package domain.commandpattern;
//厂商类
public class Light {

	public void on(){
		System.out.println("开灯啦");
	}
	
	public void off(){
		System.out.println("关灯啦");
	}
}

设计思路如图


package domain.commandpattern;
//抽象的Command接口
public interface Command {
	
	//命令的执行方法
	public void execute();
	//命令的回撤方法
	public void undo();
	
}

把开灯关灯做成命令对象

package domain.commandpattern;

public class LightOffCommand implements Command {
	private Light light;
	@Override
	public void execute() {
		light.off();
	}

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

	public LightOffCommand() {
		super();
	}

	public LightOffCommand(Light light) {
		super();
		this.light = light;
	}

	
}
package domain.commandpattern;

public class LightOnCommand implements Command {
	private Light light;
	@Override
	public void execute() {
		light.on();
	}

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

	public LightOnCommand() {
		super();
	}

	public LightOnCommand(Light light) {
		super();
		this.light = light;
	}
	
}
package domain.commandpattern;
//在未指定遥控器按钮功能时,将此作为默认
public class UnknownCommand implements Command {

	@Override
	public void execute() {
		System.out.println("未指定功能,無法執行");
	}

	@Override
	public void undo() {
		System.out.println("未指定功能,無法撤銷");
	}

}

遥控器类

package domain.commandpattern;

import java.util.Stack;

public class RemoteControl {
	
	private Command[] oncommands;
	private Command[] offcommands;
	
	private Stack<Command> previousCommand =new Stack<Command>();
	//默认遥控器按钮为7
	private int DEFAULT_Button_NUM = 7;
	//当遥控器构造出来时就把几个按钮设置成无命令的按钮
	//未指定按7按钮构造,指定了数目就按指定数目构造
	public RemoteControl(){
		oncommands = new Command[DEFAULT_Button_NUM];
		offcommands = new Command[DEFAULT_Button_NUM];
		UnknownCommand unknownCommand = new UnknownCommand();
		for (int i = 0; i < DEFAULT_Button_NUM; i++) {
			oncommands[i] = unknownCommand;
			offcommands[i] = unknownCommand;
		}
	}
	public RemoteControl(int num) {
		oncommands = new Command[num];
		offcommands = new Command[num];
		UnknownCommand unknownCommand = new UnknownCommand();
		for (int i = 0; i < num; i++) {
			oncommands[i] = unknownCommand;
			offcommands[i] = unknownCommand;
		}
	}

	public void setCommand(int index , Command oncommand , Command offcommand){
		oncommands[index] = oncommand;
		offcommands[index] = offcommand;
	}
	
	public void pressLeft(int index){
		oncommands[index].execute();
		previousCommand.push(oncommands[index]);
	}
	public void pressRight(int index){
		offcommands[index].execute();
		previousCommand.push(offcommands[index]);
	}
	public void undo(){
		if(previousCommand.isEmpty()){
			System.out.println("當前沒有任何命令被執行過");
		}else{
			previousCommand.pop().undo();
		}
	}
}

最后测试一下:

package testmethod.commandpattern;

import domain.commandpattern.Light;
import domain.commandpattern.LightOffCommand;
import domain.commandpattern.LightOnCommand;
import domain.commandpattern.RemoteControl;

public class TestCommandPattern {
	
	public static void main(String[] args) {
		//现在搞个遥控器,新买的--new的
		RemoteControl remoteControl = new RemoteControl(10);
		//厂商类,就是电灯,空调,音响,冰箱等等提供功能的类
		Light light = new Light();
		//有关灯开和关的两个指令
		LightOnCommand lightOnCommand = new LightOnCommand(light);
		LightOffCommand lightOffCommand = new LightOffCommand(light);
		//把两个指令设定到遥控器指定位置
		remoteControl.setCommand(0, lightOnCommand,lightOffCommand);
		
		System.out.println("------------过了一千年-------------");
		//有个人按了这款遥控器的按钮,0行左边按钮对应灯开指令1行左边按钮对应灯关指令
		remoteControl.pressLeft(0);
		remoteControl.pressRight(0);
		remoteControl.undo();
		remoteControl.undo();
	}
	
}
结果:

这是单个命令单个实现,也可以进行命令组合,多个命令一起执行,这个也很好设计

package domain.commandpattern;

public class CombineCommand implements Command {
	
	private Command[] allCommands;//没考虑具体细节,这个类就大概这么个意思
	
	@Override
	public void execute() {
		if(allCommands!=null && allCommands.length>0){
			for (int i = 0; i < allCommands.length; i++) {
				allCommands[i].execute();
			}
		}
	}

	@Override
	public void undo() {
		if(allCommands!=null && allCommands.length>0){
			for (int i = 0; i < allCommands.length; i++) {
				allCommands[i].undo();
			}
		}
	}

}

在Test类中,进行一个组装,把要一起执行的命令都放入到CombineCommand中,然后把CombineCommand整个作为一个键放到遥控器上,就实现了多个命令组合完成的效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值