【设计模式】Unity3D 命令模式

行为型模式——命令模式

提示:文章只是个人的学习总结。



一、命令模式是什么?

定义:
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.大话设计模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值