Unity实现设计模式——命令模式

Unity实现设计模式------命令模式

推荐一个Unity学习设计模式很好的GitHub地址:https://github.com/QianMo/Unity-Design-Pattern 有非常多的Star

一、介绍

命令模式使得请求的发送者与请求的执行者之间消除耦合,让对象之间的调用关系更加灵活。在命令模式中,会将一个命令封装成一个对象,同时命令模式也支持可撤销的操作。

命令里面通常聚合接收者,初始化命令时传入接收者,调用者直接调用命令即可

二、实现

这里使用Unity上下左右控制物体移动同时记录移动信息方便撤回为例子演示命令模式

1.ICommand

命令接口基类

csharp 复制代码
public interface ICommand
{
    void Execute();
    void UnExecute();
}

2.MoveCommand

具体的移动命令

csharp 复制代码
class MoveCommand : ICommand
{
    private MoveDirection _direction;
    private MoveCommandReceiver _receiver;
    private float _distance;
    private GameObject _gameObject;


    //Constructor
    public MoveCommand(MoveCommandReceiver reciever, MoveDirection direction, float distance,
        GameObject gameObjectToMove)
    {
        this._receiver = reciever;
        this._direction = direction;
        this._distance = distance;
        this._gameObject = gameObjectToMove;
    }


    //Execute new command
    public void Execute()
    {
        _receiver.MoveOperation(_gameObject, _direction, _distance);
    }


    //Undo last command
    public void UnExecute()
    {
        _receiver.MoveOperation(_gameObject, InverseDirection(_direction), _distance);
    }


    //invert the direction for undo
    private MoveDirection InverseDirection(MoveDirection direction)
    {
        switch (direction)
        {
            case MoveDirection.up:
                return MoveDirection.down;
            case MoveDirection.down:
                return MoveDirection.up;
            case MoveDirection.left:
                return MoveDirection.right;
            case MoveDirection.right:
                return MoveDirection.left;
            default:
                Debug.LogError("Unknown MoveDirection");
                return MoveDirection.up;
        }
    }


    //So we can show this command in debug output easily
    public override string ToString()
    {
        return _gameObject.name + " : " + MoveDirectionString(_direction) + " : " + _distance.ToString();
    }


    //Convert the MoveDirection enum to a string for debug
    public string MoveDirectionString(MoveDirection direction)
    {
        switch (direction)
        {
            case MoveDirection.up:
                return "up";
            case MoveDirection.down:
                return "down";
            case MoveDirection.left:
                return "left";
            case MoveDirection.right:
                return "right";
            default:
                return "unkown";
        }
    }
}

3.MoveCommandReceiver

命令接收者

csharp 复制代码
class MoveCommandReceiver
    {
        public void MoveOperation(GameObject gameObjectToMove, MoveDirection direction, float distance)
        {
            switch (direction)
            {
                case MoveDirection.up:
                    MoveY(gameObjectToMove, distance);
                    break;
                case MoveDirection.down:
                    MoveY(gameObjectToMove, -distance);
                    break;
                case MoveDirection.left:
                    MoveX(gameObjectToMove, -distance);
                    break;
                case MoveDirection.right:
                    MoveX(gameObjectToMove, distance);
                    break;
            }
        }

        private void MoveY(GameObject gameObjectToMove, float distance)
        {
            Vector3 newPos = gameObjectToMove.transform.position;
            newPos.y += distance;
            gameObjectToMove.transform.position = newPos;
        }

        private void MoveX(GameObject gameObjectToMove, float distance)
        {
            Vector3 newPos = gameObjectToMove.transform.position;
            newPos.x += distance;
            gameObjectToMove.transform.position = newPos;
        }
    }

4.命令的发出者(或者说是图中Clinet)

这里将命令发出者和Client放到了一起

csharp 复制代码
public class InputHandler : MonoBehaviour
{
    public float moveDistance = 10f;
    public GameObject objectToMove;

    private MoveCommandReceiver moveCommandReciever;
    private Stack<MoveCommand> commandStack1 = new Stack<MoveCommand>();
    private Stack<MoveCommand> commandStack2 = new Stack<MoveCommand>();

    void Start()
    {
        moveCommandReciever = new MoveCommandReceiver();

        if (objectToMove == null)
        {
            Debug.LogError("objectToMove must be assigned via inspector");
            this.enabled = false;
        }
    }


    public void Undo()
    {
        if (commandStack1.Count > 0)
        {
            MoveCommand moveCommand = commandStack1.Pop();
            moveCommand.UnExecute();
            commandStack2.Push(moveCommand);
        }
    }

    public void Redo()
    {
        if (commandStack2.Count > 0)
        {
            MoveCommand moveCommand = commandStack2.Pop();
            moveCommand.Execute();
            commandStack1.Push(moveCommand);
        }
    }

    private void Move(MoveDirection direction)
    {
        MoveCommand moveCommand = new MoveCommand(moveCommandReciever, direction, moveDistance, objectToMove);
        moveCommand.Execute();
        commandStack1.Push(moveCommand);
    }


    //Simple move commands to attach to UI buttons
    public void MoveUp() { Move(MoveDirection.up); }
    public void MoveDown() { Move(MoveDirection.down); }
    public void MoveLeft() { Move(MoveDirection.left); }
    public void MoveRight() { Move(MoveDirection.right); }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            MoveUp();
        }
        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            MoveDown();
        }
        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            MoveLeft();
        }
        if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            MoveRight();
        }
        if (Input.GetKeyDown(KeyCode.R))
        {
            Redo();
        }
        if (Input.GetKeyDown(KeyCode.U))
        {
            Undo();
        }
    }
}
相关推荐
蔡蓝2 小时前
设计模式-建造者模式
服务器·设计模式·建造者模式
不伤欣7 小时前
游戏设计模式 - 子类沙箱
游戏·unity·设计模式
漫谈网络7 小时前
MVC与MVP设计模式对比详解
设计模式·mvc
蔡蓝7 小时前
设计模式-观察着模式
java·开发语言·设计模式
哆啦A梦的口袋呀9 小时前
基于Python学习《Head First设计模式》第六章 命令模式
python·学习·设计模式
半路下车10 小时前
【Harmony OS 5】HarmonyOS应用测试指南
设计模式·harmonyos
周某某~10 小时前
一.设计模式的基本概念
设计模式
on the way 12310 小时前
行为型设计模式之Interpreter(解释器)
设计模式
cui_hao_nan10 小时前
设计模式——模板方法
java·设计模式
在未来等你10 小时前
Java并发编程实战 Day 11:并发设计模式
java·设计模式·多线程·并发编程·threadlocal·生产者消费者·读写锁