设计模式——命令模式

COMMAND 命令

 

1、 意图

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排列或记录请求日志,以及支持可撤销的操作。

2、 别名

动作(Action)、事务(Transaction)

3、 适用性

  • 抽象出呆执行的动作以参数化某对象。可以用语言中的回调(callback)函数表达这种参数化机制。Command模式是回调机制的一个面向对象的替代品。
  • 在不同的时刻指定、排列和执行请求。一个Command对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可将负责请求的命令对象传给另一个不同的进程并在那儿实现该请求。
  • 支持取消操作。Command的Excute操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。Command接口必须添加一个Unexecute操作,该操作取消上一次Execute调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并调用Unexecute和Execute来实现重数不限的“取消”和“重做”。
  •  支持修改日志。
  • 用构建在原来操作上的高层操作构造一个系统。这种结构在支持事务的信息系统中很常见。一个事务封装了对数据的一组变动。Command模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用一种方式调用所有的事务。同时该模式也易于添加新事务以扩展系统。

4、 结构


5、 参与者

Command

           ——声明执行操作的接口。

ConcreteCommand

           ——将一个接收者对象绑定于一个动作。

           ——调用接收者相应的操作,以实现Execute。

Client

           ——创建一个具体命令对象并设定它的接收者。

Invoker

           ——要求该命令执行这个请求。

Receiver

           ——知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。


6、 协作

  • Client创建一个ConcreteCommand对象并指定它的Receiver对象。
  • 某Invoker对象存储该ConcreteCommand对象。
  • 该Invoker通过调用Command对象的Execute操作来提交一个请求。如该命令是可撤销的,ConcreteCommand就在执行的Execute操作之前存储当前状态以用于取消该命令。
  • ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求。

7、 效果

Command模式有以下效果:

1)  Command模式将调用操作的对象与知道如何实现该操作的对象解耦。

2)  Command是头等的对象。它们可像其他的对象一样呗操纵和扩展。

3)  你可将多个命令装配成一个复和命令。

4)  增加新的Command很容易,因为这无需改变已有的类。

8、 实现

1)  一个命令对象应达到何种智能程度;命令对象的能力可大可小,一个极端是它仅确定一个接收者和执行该请求的动作。另一个极端是它自己实现所有功能,根本不需要额外的接受对象。

2)  支持取消和重做;

3)  避免取消操作过程中的错误积累;

9、 代码示例

 Command

package com.examples.pattern.command;

/**   
* 命令接口,声明执行的操作    
*/
public interface Command {
	
	/**
	 * 执行命令对应的操作
	 */
	public void execute();

}
ConcreteCommand

package com.examples.pattern.command;

/**   
*  具体的命令实现对象  
*/
public class ConcreteCommand implements Command {
	
	/**
	 * 持有相应的接收者对象
	 */
	private Receiver receiver = null;
	
	

	/**
	 * 构造方法,传入相应的接收者对象
	 * @param receiver
	 */
	public ConcreteCommand(Receiver receiver) {
		this.receiver = receiver;
	}



	@Override
	public void execute() {
		receiver.action();
	}

}
Client

package com.examples.pattern.command;

public class Client {

	public void assemble(){
		//创建接收者
		Receiver receiver = new Receiver();
		//创建命令对象,设定它的接收者
		Command command = new ConcreteCommand(receiver);
		//创建Invoker,把命令对象设置进去
		Invoker invoker = new Invoker();
		invoker.setCommand(command);
		command.execute();
	}
	
	public static void main(String[] args) {
		Client client = new Client();
		client.assemble();
	}
	
	
}
Invoker

package com.examples.pattern.command;

/**   
* 调用者  
*/
public class Invoker {
	
	/**
	 * 持有命令对象
	 */
	private Command command = null;

	/**
	 * 设置调用持有者的命令对象
	 * @param command
	 */
	public void setCommand(Command command) {
		this.command = command;
	}
	
	public void runCommand(){
		//调用命令对象的执行方法
		command.execute();
	}
	

}
Receiver

package com.examples.pattern.command;

/**   
* 接收者对象   
*/
public class Receiver {

	/**
	 * 真正执行命令相应的操作
	 */
	public void action() {
		System.out.println("this is an anction");
	}

}


10、相关模式

Composite模式可被用来实现宏命令。

Memento模式可用来保持某个状态,命令用这一状态来取消它的效果。

 


### Java 中命令模式Command Pattern)的实现与示例 #### 1. 命令模式的核心概念 命令模式是一种行为型设计模式,其核心目标是将请求封装为一个对象,从而使不同类型的请求可以被参数化处理。这种方式不仅实现了请求发送者和接收者的解耦[^2],还提供了诸如撤销、重做以及日志记录等功能的支持。 #### 2. 核心角色及其职责 以下是命令模式的主要组成部分及其作用: - **命令接口(Command Interface)**: 定义了一个 `execute()` 方法用于执行命令,还可以定义 `undo()` 方法用于撤销命令。 - **具体命令(Concrete Command)**: 实现了命令接口,并绑定了具体的接收者与其操作方法。 - **接收者(Receiver)**: 执行实际的操作逻辑。 - **调用者(Invoker)**: 负责触发命令的执行,通常会持有某个命令对象的引用。 - **客户端(Client)**: 创建具体命令对象并将其与相应的接收者关联起来[^4]。 #### 3. 遥控器控制家电的经典示例 ##### 步骤 1:定义命令接口 ```java public interface Command { void execute(); } ``` ##### 步骤 2:实现接收者(家电类) 假设我们有一个简单的电灯作为接收者: ```java public class Light { public void turnOn() { System.out.println("Light is ON"); } public void turnOff() { System.out.println("Light is OFF"); } } ``` ##### 步骤 3:实现具体命令类 针对上述电灯的功能,分别创建打开和关闭的具体命令: ```java public class TurnOnLightCommand implements Command { private final Light light; public TurnOnLightCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOn(); } } public class TurnOffLightCommand implements Command { private final Light light; public TurnOffLightCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOff(); } } ``` ##### 步骤 4:实现调用者(遥控器) 遥控器作为一个调用者,负责存储当前的命令并通过按钮触发该命令: ```java public class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { if (command != null) { command.execute(); } else { System.out.println("No command set."); } } } ``` ##### 步骤 5:客户端调用 最后,在客户端中完成整个流程的组装和测试: ```java public class Client { public static void main(String[] args) { // 接收者 Light livingRoomLight = new Light(); // 具体命令 Command onCommand = new TurnOnLightCommand(livingRoomLight); Command offCommand = new TurnOffLightCommand(livingRoomLight); // 调用者 RemoteControl remote = new RemoteControl(); // 设置并执行开灯命令 remote.setCommand(onCommand); remote.pressButton(); // 输出: Light is ON // 设置并执行关灯命令 remote.setCommand(offCommand); remote.pressButton(); // 输出: Light is OFF } } ``` #### 4. 支持宏命令(批量操作) 为了支持更复杂的场景,比如一次执行多个命令,可以通过引入宏命令来实现。下面是一个简单示例: ##### 步骤 1:定义宏命令类 ```java import java.util.ArrayList; import java.util.List; public class MacroCommand implements Command { private List<Command> commands = new ArrayList<>(); public void addCommand(Command command) { commands.add(command); } public void removeCommand(Command command) { commands.remove(command); } @Override public void execute() { for (Command cmd : commands) { cmd.execute(); } } } ``` ##### 步骤 2:客户端使用宏命令 ```java public class ClientWithMacro { public static void main(String[] args) { Light kitchenLight = new Light(); Light bedroomLight = new Light(); Command kitchenOn = new TurnOnLightCommand(kitchenLight); Command kitchenOff = new TurnOffLightCommand(kitchenLight); Command bedroomOn = new TurnOnLightCommand(bedroomLight); Command bedroomOff = new TurnOffLightCommand(bedroomLight); MacroCommand macroCommand = new MacroCommand(); macroCommand.addCommand(kitchenOn); macroCommand.addCommand(bedroomOn); RemoteControl remote = new RemoteControl(); remote.setCommand(macroCommand); remote.pressButton(); // 同时开启厨房和卧室灯光 } } ``` #### 5. 总结 通过以上实例可以看出,命令模式在分离请求发起方与执行方的同时,也增强了系统的灵活性和可维护性。然而需要注意的是,过多的命令可能会导致系统变得臃肿,因此应权衡利弊合理应用。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值