行为型模式——命令模式
提示:文章只是个人的学习总结。
文章目录
一、命令模式是什么?
定义:
1.将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作。
2.命令模式是一种回调的面向对象实现。
二、UML图
TODO
三、Unity/C#实现
1.抽象命令类(Command)
1.可以定义一个接收者或者在方法中传入控制的角色对象
2.在抽象类里通常使用虚(virtul)方法
public abstract class Command {
protected float _TheTime;
public float TheTime
{
get { return _TheTime; }
}
//执行
public virtual void execute(Avatar avatar) { }
//撤销回滚
public virtual void undo(Avatar avatar) { }
}
2.具体命令类(Concrete Command)
1.是抽象命令类或者接口的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
2.也可以在execute方法中存储之前的状态
using UnityEngine;
public class CommandMove : Command {
private Vector3 TransPos;
//可以写成构造方法
public CommandMove(Vector3 transPos, float time)
{
TransPos = transPos;
_TheTime = time;
}
public override void execute(Avatar avatar)
{
avatar.Move(TransPos);
}
public override void undo(Avatar avatar)
{
avatar.Move(-TransPos);
}
}
3.现者/接收者(Receiver)
执行具体命令的对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Avatar : MonoBehaviour {
private Transform mTransform;
void Start () {
mTransform = transform;
}
//移动
public void Move(Vector3 DeltaV3)
{
mTransform.Translate(DeltaV3);
}
}
4.调用者/请求者(Invoker)
1.是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求。
2.它不直接访问接收者,与具体执行的操作对象分开
3.创建命令数据队列或栈可以轻易实现撤销、重做
4.封装各种请求为命令对象
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CommandManager : MonoBehaviour
{
//
public Avatar TheAvatar;
//命令栈实现撤销
private Stack<Command> mCommandStack;
private float mCallBackTime;
//执行或撤销的标志
public bool IsRun = true;
void Start()
{
mCommandStack = new Stack<Command>();
mCallBackTime = 0;
}
void Update()
{
if (IsRun)
{
Control();
}
else
{
RunCallBack();
}
}
//撤销
private void RunCallBack()
{
mCallBackTime -= Time.deltaTime;
//栈非空时可执行撤销操作
if (mCommandStack.Count > 0 && mCallBackTime < mCommandStack.Peek().TheTime)
{
mCommandStack.Pop().undo(TheAvatar);
}
}
//执行
private void Control()
{
mCallBackTime += Time.deltaTime;
Command cmd = InputHandler();
if (cmd != null)
{
//进栈
mCommandStack.Push(cmd);
//执行命令
cmd.execute(TheAvatar);
}
}
//命令构造:此时将请求封装为一个对象,存进命令栈
private Command InputHandler()
{
if (Input.GetKey(KeyCode.W))
{
return new CommandMove(new Vector3(0, Time.deltaTime, 0), mCallBackTime);
}
if (Input.GetKey(KeyCode.S))
{
return new CommandMove(new Vector3(0, -Time.deltaTime, 0), mCallBackTime);
}
if (Input.GetKey(KeyCode.A))
{
return new CommandMove(new Vector3(-Time.deltaTime, 0, 0), mCallBackTime);
}
if (Input.GetKey(KeyCode.D))
{
return new CommandMove(new Vector3(Time.deltaTime, 0, 0), mCallBackTime);
}
return null;
}
}
四、优缺点
优点:
1.可以简单实现撤销和重做
2.由于加进新的具体命令不影响其他的类,不会造成开发混乱
3.请求一个操作的对象和知道怎么执行一个操作的对象分割开。
五、适用场景
1.在需要撤销/恢复操作等功能时,如各种编辑器功能,ctrl+Z
附
提示:个人学习和参考所引用的知识链接
1.游戏设计模式
2.大话设计模式