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();
        }
    }
}
相关推荐
闲人一枚(学习中)40 分钟前
设计模式-创建型-抽象工厂模式
设计模式·抽象工厂模式
小白不太白9503 小时前
设计模式之 观察者模式
观察者模式·设计模式
小白不太白9504 小时前
设计模式之 责任链模式
python·设计模式·责任链模式
吾与谁归in5 小时前
【C#设计模式(13)——代理模式(Proxy Pattern)】
设计模式·c#·代理模式
吾与谁归in5 小时前
【C#设计模式(14)——责任链模式( Chain-of-responsibility Pattern)】
设计模式·c#·责任链模式
闲人一枚(学习中)5 小时前
设计模式-创建型-原型模式
设计模式
Iced_Sheep5 小时前
干掉 if else 之策略模式
后端·设计模式
哪 吒13 小时前
最简单的设计模式,抽象工厂模式,是否属于过度设计?
设计模式·抽象工厂模式
Theodore_102213 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
向宇it15 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎