Head First 设计模式笔记 5.命令模式

文章目录

设计要求

小明接到了新任务,要求设计一个遥控器,这个遥控器上面有七个插槽,每个插槽都有对应的开和关按钮。要求每个都能控制任意家电如灯,电视,电风扇,门等等。以下是这些家电的类图

Head First 设计模式笔记 5.命令模式
图1 家具的类图

小明本想用if-else语句进行判断插槽slot上面的对象,在进行的对应,如

if(slot == light)
	light.on()
else if(slot == sprinkler)
	sprinkler.on()

但是很快小明就发现了问题。

  • 假如未来有新的家电加入,就必须修改代码。违法了对扩展开放,对修改关闭的设计原则
  • 有些家电还具有自己特殊的方法,比如电视机有调节声音的setVolunm()方法。而现在无法支持除了on()和off()以外的方法。

小明发现,问题的关键在于,动作请求者和动作执行者紧紧地捆绑在了一起。请求者就是遥控器,执行者就是各种家电。能不能找个中间商,协调一下两者呢?

命令模式

小明查阅了设计模式葵花宝典后,发现还真的有个命令模式,可以完美地实现动作请求者和动作执行者解耦的问题。在命令模式中,请求或者说命令被视为一种对象,用于沟通动作请求者和动作执行者。它具有以下几个角色

  • 命令对象,用于传递命令
  • 执行对象,用于执行对应的命令
  • 请求对象,用于发出请求
  • Invoker,提供使用命令对象的入口

基本流程是,请求对象创建一个命令对象,之后将命令对象存储在Invoker中,之后,客户通过Invoker执行命令。

它的类图如图所示

Head First 设计模式笔记 5.命令模式
图2 命令模式的类图

实际实现

掌握了命令模式后,小明就可以根据按照套路进行设计了。

命令对象的设计

先来一个命令接口

public interface Command {
	public void execute();
}

再来一个控制灯泡打开的具体命令

public class LightOnCommand implements Command {
	Light light;
  
	public LightOnCommand(Light light) {
		this.light = light;
	}
 
	public void execute() {
		light.on();
	}
}

遥控器的设计

这里我们设计一个最简单的遥控器,它只有一个插槽,负责打开一个装置。

public class SimpleRemoteControl {
	Command slot;
 
	public SimpleRemoteControl() {}
 
	public void setCommand(Command command) {
		slot = command;
	}
 
	public void buttonWasPressed() {
		slot.execute();
	}
}

简单测试

最后,来一个简单的测试。

public class RemoteControlTest {
	public static void main(String[] args) {
		SimpleRemoteControl remote = new SimpleRemoteControl();
		
		Light light = new Light();
		LightOnCommand lightOn = new LightOnCommand(light);
		
		remote.setCommand(lightOn);
		remote.buttonWasPressed();
    }
	
}

在上述的具体实现中,remote就是invoker,而command对应command,而RemoteControlTest代表client,最后light则是reciever。

命令模式具体应用

队列请求

命令模式可以处理队列请求,假设有一个工作队列,客户在一端添加命令,然后另外一端是线程,线程在队列中取出一个命令,调用它的execute方法,等待这个调用完成,然后将这个命令对象抛弃,再取出下一个命令。

日志请求

某些应用要求我们将所有的动作记录在日志中,并在系统死机后,调用这些动作恢复到原来的状态。命令模式可以把这些动作记录为一个个命令对象,持久化存储在磁盘中,一旦死机,我们就可以将这些命令对象重新加载并且调用它们的execute()方法。实现恢复。

上一篇:Js控制网页鼠标滚动时,顶部导航条,由透明变成有背景色


下一篇:2021-03-18:给定一个字符串str,只由‘X’和‘.’两种字符构成。‘X’表示墙,不能放灯,