命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作。
命令模式是一种回调的面向对象实现

UML

在这里插入图片描述
图片源自《大话设计模式》

实现

//用来声明执行操作的接口
abstract class Command
{
	protected Receiver receiver;
	public Command(Receiver receiver)
	{
		this.receiver = receiver;
	}

	abstract public void Execute();
}

//将一个接受者对象绑定于一个动作,调用接受者相应的操作,以实现Excute
class ConcreteCommand:Command
{
	public ConcreteCommand(Receiver receiver):base(receiver)
	{ }

	public override void Execute()
	{
		receiver.Action();
	}
}

//要求该命令执行这个请求
class Invoker
{
	private Command command;

	public void SetCommand(Command command)
	{
		this.command = command;
	}

	public void ExecuteCommand()
	{
		command.Execute();
	}
}

//知道如何实施与执行一个与请求相关的操作,任何类都可能成为一个接受者
class Receiver
{
	public void Action()
	{
		Console.WriteLine("请求执行!");
	}
}

//客户端代码,创建一个具体命令对象并设定它的接受者
static void Main(string[] args)
{
	Receiver r = new Receiver();
	Command c = new Command();
	Invoker i = new Invoker();

	i.SetCommand(c);
	i.ExecuteCommand();

	Console.Read();
}

优点

  • 能较容易的设计一个命令队列
  • 在需要的情况下,可以容易的将命令记入日志
  • 允许接受请求的一方决定是否要否决请求
  • 可以容易地实现对请求的撤销和重做
  • 由于添加新的具体命令类(ConcreteCommand)不影响其他的类,因此增加新的具体命令类很容易
  • 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开

应用

配置输入

一般的输入命令:

void Update () {
            if (Input.GetKeyDown(KeyCode.W)) Jump();
            if (Input.GetKeyDown(KeyCode.S)) GetDown();
            if (Input.GetKeyDown(KeyCode.A)) Defense();
            if (Input.GetKeyDown(KeyCode.D)) Attack();
    }

为了支持可以配置按键功能,需要将这些对Jump()和Attack()的直接调用转化为可以变换的东西。

撤销和重做