设计模式之Command

一、Command模式基本介绍

Command模式,也称为行动模式或事务模式,用于将请求封装为一个对象,从而实现行为的解耦和灵活性。 这种模式特别适用于需要记录、撤销或重做操作的情况,因为它允许系统在运行时动态地处理请求。

定义与结构: Command模式定义了一个命令的接口(Command),声明了执行的方法。具体命令(ConcreteCommand)是命令接口的实现,通常持有接收者(Receiver)并调用其功能来完成命令要执行的操作。接收者是真正执行命令的对象,而客户端(Client)创建具体的命令对象并设置其接收者。

角色与协作: 在这个模式中,有几个关键角色:命令(Command)、具体命令(ConcreteCommand)、接收者(Receiver)、调用者(Invoker)和客户端(Client)。客户端创建具体的命令对象并设置其接收者。调用者持有命令对象,并通过调用命令对象的Execute方法来提交请求。

应用场景: Command模式广泛应用于需要高灵活性和可维护性的系统中,如菜单命令、撤销操作、游戏动作组合等。通过将操作封装为命令对象,系统可以在不修改原有代码的情况下增加新的操作或修改已有操作的行为。

优点与缺点: 优点包括类间的解耦、可扩展性以及支持撤销操作等。缺点是如果系统中存在大量的命令,可能会导致Command类的数量增多,增加系统的复杂性。

 二、场景实现例子

场景:实现一个拨号功能,要求不同的按钮播放不同的声音,最后组合后拨号。

先看Client代码 

package command;

/**
 * 负责创建各个类,并且组装命令
 */
public class Client {
	public static void main(String[] args) {
		Invoker invoker = new Invoker();
		Receiver receiver = new Receiver();
		invoker.addCommand(new NumberCommand(1, receiver));
		invoker.addCommand(new NumberCommand(3, receiver));
		invoker.addCommand(new NumberCommand(5, receiver));
		invoker.addCommand(new NumberCommand(3, receiver));
		invoker.addCommand(new NumberCommand(5, receiver));
		invoker.addCommand(new NumberCommand(17, receiver));
		invoker.addCommand(new DialCommand(receiver));
		invoker.dialPhone();
	}
}

Invoker

package command;

import java.util.ArrayList;
import java.util.List;

/**
 * 拨号器
 */
public class Invoker {
	private List<Command> commandList;

	public Invoker() {
		commandList = new ArrayList<Command>();
	}

	public void addCommand(Command command) {
		commandList.add(command);
	}

	/**
	 * Command的组合调用,可以灵活用于命令编排,类似游戏中的动作组合,非常有用
	 */
	public void dialPhone() {
		for (Command command : commandList) {
			command.execute();
		}
		commandList.clear();
	}

}

命令接口Command

package command;

public interface Command {

	public void execute();

}

 数字类号码播放命令

package command;

/**
 * 数字按钮
 */
public class NumberCommand implements Command {
	private Integer num;
	private Receiver receiver;

	public NumberCommand(Integer num, Receiver receiver) {
		this.num = num;
		this.receiver = receiver;
	}

	@Override
	public void execute() {
		System.out.println("播放按钮" + num + "声音,并亮灯");
		receiver.addNum(num);
	}

}

 拨号按钮命令

package command;

/**
 * 拨号按钮
 */
public class DialCommand implements Command {
	private Receiver receiver;

	public DialCommand(Receiver receiver) {
		this.receiver = receiver;
	}

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

 干苦活累活的命令接收者Receiver

package command;

import java.util.ArrayList;
import java.util.List;

/**
 * 命令的接收者,这里输入号码和拨号,都是同一个接收者,我们定义两个方法
 */
public class Receiver {
	// 存储电话号码
	private List<Integer> numList;

	public Receiver() {
		this.numList = new ArrayList<Integer>();
	}

	public void addNum(Integer num) {
		System.out.println("本地存储按按钮数字:" + num);
		numList.add(num);
	}

	public void dial() {
		System.out.println("拨号中,号码为" + numList);
		numList.clear();
	}
}

Client代码执行效果:

 

三、结束语

通过上面一个简单的例子,让我们对命令模式的灵活性有很好的理解,现实场景中,使用命令模式,比较复杂的应该是接收者的实现。学了这个后,我们以后对各种开关按钮等功能实现,软件界面的执行及回撤等,都可以使用命令模式。

如果觉得不错,请收藏或者点赞支持,小红点是我持续更新的动力之一,感谢~

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值