在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式(Command Pattern)。
1、适用场景
(1)系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
(2)系统需要在不同的时间指定请求、将请求排队和执行请求。2、模式分析
(1).命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。 (2).每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。 (3).命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。 (4).命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。 (5).命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。3、模式优点
(1).降低对象之间的耦合度。 (2).新的命令可以很容易地加入到系统中。 (3).可以比较容易地设计一个组合命令。 (4).调用同一方法实现不同的功能4、模式缺点
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。5、代码实现
(1)结构图
(2)实现代码
//模拟一个开关灯的操作命令public class TestCommand { public static void main(String[] args) { Light testLight = new Light(); LightOnCommand testLOC = new LightOnCommand(testLight); LightOffCommand testLFC = new LightOffCommand(testLight); Switch testSwitch = new Switch(testLOC, testLFC); testSwitch.flipUp( ); testSwitch.flipDown( ); }} //----------------------------------------------------- //---------- Class Light ---------------------------- class Light { public void turnOn() { System.out.println("Light is on now !"); } public void turnOff() { System.out.println("Light is off now !"); } } //----------------------------------------------------- //---------- Class Switch --------------------------- class Switch { private Command UpCommand, DownCommand; public Switch (Command Up, Command Down) { UpCommand = Up; DownCommand = Down; } void flipUp() { UpCommand.execute(); } void flipDown() { DownCommand.execute(); } } //----------------------------------------------------- //---------- Class LightOnCommand ------------------- class LightOnCommand implements Command { private Light myLight; public LightOnCommand (Light L) { myLight = L; } public void execute() { myLight.turnOn(); } } //----------------------------------------------------- //---------- Class LightOffCommand ------------------ class LightOffCommand implements Command { private Light myLight; public LightOffCommand (Light L) { myLight = L; } public void execute() { myLight.turnOff(); } }