设计模式学习-简单的命令模式例子

上一章节介绍过了命令模式,这一篇文章就简单的做一个小案例来巩固学习

搭建场景

简单的搭建一个场景就行 ,随便准备一个物体放在场景中位置Reset一下即可。

代码编写
  1. 定义接口(或者抽象类)ICommand 用来规范Command的行为。注意在命令模式中命令是桥接作用负责接受者和执行者之间的联调。所以一般会有很多的命令,每个命令都会有ICommand规范的方法同时也可以添加其他的方法。
csharp 复制代码
public interface ICommand{
	void Execute();
	void UnExecute();
}
  1. 实现定义的接口(或者抽象类) 同时为了具有这种桥接的作用,MyCommand 需要持有Receiver
csharp 复制代码
public enum Direction{
	Left,
	Down,
	Right,
	Up
}
public class MyCommand : ICommand{
	private Receiver _receiver;
	private Direction _direction;
	private GameObject _moveObj;
	private float _distance;
	
	public MyCommand(Direction direction,Receiver receiver,GameObject moveObj,float distance){
		this._receiver = receiver;
		this._direction = direction;
		this._moveObj = moveObj;
		this._distance = distance;
	}
	public void Execute(){
		_receiver.OperationDirection(_moveObj,_direction,_distance );
	}
	public void UnExecute(){
		_receiver.OperationDirection(_moveObj,InverseDirection(_direction),_distance );
	}
	private Direction InverseDirection(Direction direction){
		switch(direction){
		case Direction.Left:
			return Direction.Right;
		case Direction.Right:
			return Direction.Left;
		case Direction.Up:
			return Direction.Down;
		case Direction.Down:
			return Direction.Up;
		}
	}

	public override void ToString(){
		return $"{_moveObj.name}:{DirectionStr(_direction)}:{_distance.ToString()}";
	}
	private string DirectionStr(Direction dircteion) {
    switch (dircteion) 
    { 
        case Direction.Left:
            return "Left";
        case Direction.Right:
            return "Right";
        case Direction.Up:
            return "Up";
        case Direction.Down:
            return "Down";
        default:
            return default;
    }
}
}

3.接受者,接受者的意思是接受命令执行自身的函数

csharp 复制代码
public class Receiver{
	public void OperationDirection(GameObject moveObj,Direction direction,float distance){
		switch(direction){
		case Direction.Left:
			MoveX(moveObj,-distance);
			break;
		case Direction.Right:
			MoveX(moveObj,distance);
			break;
		case Direction.Up:
			MoveY(moveObj,distance);
			break;
		case Direction.Up:
			MoveY(moveObj,-distance);
			break;
		}
	}
	
	private void MoveX(GameObject moveObj,float distance){
		var tempPos = moveObj.transform.position;
		tempPos .x+=distance;
		moveObj.transform.position = tempPos;
	}
	private void MoveY(GameObject moveObj,float distance){
		var tempPos = moveObj.transform.position;
		tempPos.y+=distance;
		moveObj.transform.position = tempPos;
	}
}

4.执行者,挂载在场景中的任意物体上(建议放空物体上)负责代码的执行 调度

csharp 复制代码
public class InputHandler : MonoBehaviour{
	private Receiver _receiver;
	[SerializeField]
    [Tooltip("移动距离")]
	private float distance = 1f;
	private List<ICommand> commands = new List<ICommand>(); // 存储命令方便回溯
 	private int currentCommandNum = 0;  // 当前执行的命令
 	public GameObject moveObj;  //控制的物体上面的那个Move直接拖到这里进行绑定 
	
	private void Start()
	{
    	_receiver= new Receiver();
		// 空处理 可写可不写
	}
	private void Move(Direction direction){
		var command = new MyCommand(direction,_receiver,moveObj,distance);
		command.Execute();
		commands.Add(command);
		currentCommandNum++;
	}
	private void Undo(){
		if(currentCommandNum > 0 ){
			currentCommandNum--;
			MyCommand command= (MyCommand )commands[currentCommandNum];
			command.UnExecute();
		}
	}
	private void Redo(){
		if (currentCommandNum < commands.Count) { 
	    MyCommand command= (MyCommand )commands[currentCommandNum];
	    currentCommandNum++;
	    command.Execute();
		}
	}
	void OnGUI()
	{
	    string label = "   start";
	    if (currentCommandNum == 0)
	    {
	        label = ">" + label;
	    }
	    label += "\n";
	
	    for (int i = 0; i < commands.Count; i++)
	    {
	        if (i == currentCommandNum - 1)
	            label += "> " + commands[i].ToString() + "\n";
	        else
	            label += "   " + commands[i].ToString() + "\n";
	    }
	    GUI.Label(new Rect(0, 0, 400, 800), label);
	}
	 private void Update()
		 {
		     if (Input.GetKeyDown(KeyCode.UpArrow)|| Input.GetKeyDown(KeyCode.W)) 
		     { moveUp(); }
		     if (Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.S)) 
		     { moveDown(); }
		     if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A))
		      { moveLeft(); }
		     if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D)) 
		     { moveRight(); }
		     if (Input.GetKeyDown(KeyCode.R))
		     { Redo(); }
		     if (Input.GetKeyDown(KeyCode.U))
		     { Undo(); }
		 }
	 void moveUp() { Move(Direction.Up); }
	 void moveDown() { Move(Direction.Down); }
	 void moveLeft() {  Move(Direction.Left); }
	 void moveRight() { Move(Direction.Right); }
}

现在就基本上已经做完了,是一个很简单的案例用来巩固学习命令模式

相关推荐
蔚一12 分钟前
Java设计模式—面向对象设计原则(六) ----->合成复用原则(CRP) (完整详解,附有代码+案例)
xml·java·开发语言·设计模式·intellij-idea·合成复用原则
ok!ko16 分钟前
设计模式之建造者模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·建造者模式
Filotimo_25 分钟前
使用 Anaconda 环境在Jupyter和PyCharm 中进行开发
ide·经验分享·笔记·python·学习·jupyter·pycharm
mljy.36 分钟前
C/C++内存管理
c++·学习
Hcoco_me1 小时前
面试爱考 | 设计模式
java·c++·设计模式·面试
Yasin Chen1 小时前
Unity 粒子系统参数说明
unity·游戏引擎
冰凌糕1 小时前
Unity3D 小案例 像素贪吃蛇 02 蛇的觅食
unity
血不热了1 小时前
Qt:懒汉单例(附带单例使用和内存管理)
开发语言·qt·设计模式
躺下睡觉~1 小时前
Unity—Transform类-position
unity·游戏引擎
宁子希1 小时前
一,掌心里的智慧:我的 TinyML 学习之旅
人工智能·学习