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

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

搭建场景

简单的搭建一个场景就行 ,随便准备一个物体放在场景中位置Reset一下即可。
在这里插入图片描述

代码编写
  1. 定义接口(或者抽象类)ICommand 用来规范Command的行为。注意在命令模式中命令是桥接作用负责接受者和执行者之间的联调。所以一般会有很多的命令,每个命令都会有ICommand规范的方法同时也可以添加其他的方法。
public interface ICommand{
	void Execute();
	void UnExecute();
}
  1. 实现定义的接口(或者抽象类) 同时为了具有这种桥接的作用,MyCommand 需要持有Receiver
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.接受者,接受者的意思是接受命令执行自身的函数

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.执行者,挂载在场景中的任意物体上(建议放空物体上)负责代码的执行 调度

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); }
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/872108.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux查看jar包错误日志及持久化运行jar包

一、查看jar包运行信息命令&#xff1a;ps -ef | grep java 如图&#xff0c;给出了所部署jar包的环境变量&#xff0c;服务名称&#xff0c;服务端口信息。 这样便能得到部署的jar包是否在服务器成功运行及基本信息。 二、查看日志 启动信息无误&#xff0c;查看日志是否有报错…

SprinBoot+Vue在线商城微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平…

基于ssm+vue+uniapp的跑腿平台小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

SSM非物质文化遗产社区APP---附源码98956

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

使用el-select只能选中最后一项,且options全部是选中状态

经过盘查,发现是key值重复了 把key值换为不同的值就好了,很细小的问题,但是很容易疏忽.

Android Studio(3) 使用 Kotlin DSL和 Gradle 8.7 打包远程库到 AAR 的自定义方法

背景介绍 在 Gradle 7.3 及更早版本中,通常使用 com.kezong.fat-aar 插件来打包远程库到 AAR 中,随着 Gradle 的不断升级,尤其是到 8.7 版本后,Kotlin DSL开发逐渐成为主流,fat-aar 社区没有更新,插件的兼容性问题逐渐显现。我探索一种新的自定义方法,能够在 Kotlin DS…

C#归并排序算法

前言 归并排序是一种常见的排序算法&#xff0c;它采用分治法的思想&#xff0c;在排序过程中不断将待排序序列分割成更小的子序列&#xff0c;直到每个子序列中只剩下一个元素&#xff0c;然后将这些子序列两两合并并排序&#xff0c;最终得到一个有序的序列。 归并排序实现原…

第T9周:使用TensorFlow实现猫狗识别2

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文章目录 一、前期工作1.设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;2. 导入数据 二、数据预处理1、加载数据2、再次检查数据3、可视化数据3…

【C++题解】1053 - 求100+97+……+4+1的值。

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1053 - 求10097……41的值。 类型&#xff1a;简单循环 题目描述&#xff1a; 求 10097⋯41 的值。 输入&#xff1a; 无。 输出&#xff1a; 输出一行&#xff0c;即求到的和…

Linux--网络层 IP协议

目录 0.往期文章 1.IP基本概念 2. IP协议报头格式 3.网段划分 两种网段划分的方式 为什么要进行网段划分 4.特殊的IP 地址 5.IP 地址的数量限制 6.私有 IP 地址和公网 IP 地址*** NAT技术 认识公网 运营商扮演的角色 7.路由 8.16位标识&#xff0c;3为标志和13位…

加速自动驾驶模型迭代,数据存算一体是关键

自动驾驶的每一个业务阶段都会涉及到 AI 深度学习算法和算力的参与&#xff0c;机器视觉&#xff0c;深度学习&#xff0c;传感器技术等均在自动驾驶领域发挥着重要的作用。自动驾驶系统不断迭代的前提是算法的持续优化&#xff0c;目前&#xff0c;自动驾驶发展的瓶颈主要在于…

解决ubuntu22.04无法识别CH340/CH341和vscode espidf插件无法选择串口设备节点问题

文章目录 解决ubuntu22.04无法识别CH340/CH341和vscode espidf插件无法选择串口设备节点问题不识别CH340/CH341报错解决办法升级驱动编译安装 卸载brltty程序 vscode espidf插件无法选择串口设备节点问题解决办法编译安装 解决ubuntu22.04无法识别CH340/CH341和vscode espidf插…

坐标大连!提交EI、Scopus、知网检索!第五届经济管理与大数据应用国际学术会议(ICEMBDA 2024)

合作ACM出版-EI稳检索 高录用&#xff0c;快见刊&#xff01; 管理、经济、金融、计算机相关主题均可投稿 目前仍有口头汇报名额&#xff0c;如有需要请尽快报名 重要信息 会议官网&#xff1a;www.icembda.org 会议时间&#xff1a;2024年10月25日-27日 会议地点&#x…

【Python系列】方法返回2个值

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

spring security 入门基础,表单认证web页面跳转

一、导入所需依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version></parent><!-- web 支持 --><dependency><groupId>…

FPGA 综合笔记

仿真时阻塞赋值和非阻塞赋值 Use of Non-Blocking Assignment in Testbench : Verilog Use of Non-Blocking Assignment in Testbench : Verilog - Stack Overflow non-blocking assignment does not work as expected in Verilog non-blocking assignment does not work a…

Linux云计算 |【第二阶段】SECURITY-DAY3

主要内容&#xff1a; Prometheus监控服务器、Prometheus被监控端、Grafana监控可视化 补充&#xff1a;Zabbix监控软件不自带LNMP和DB数据库&#xff0c;需要自行手动安装配置&#xff1b;Prometheus监控软件自带WEB页面和DB数据库&#xff1b;Prometheus数据库为时序数据库&…

adaptive AUTOSAR UCM模块中SoftwareCluster与Software Package是什么样的关系,他们分别包含哪些元素?

在自适应AUTOSAR(Adaptive AUTOSAR)的更新和配置管理(UCM)模块中,SoftwareCluster和Software Package是软件更新过程中的两个关键概念,它们之间有着密切的关系: SoftwareCluster:通常指的是一组功能相关的软件组件,它们共同实现了车辆中的一个或多个特定功能。在UCM中…

柔性织物处理 | 山大宋锐老师 | 最新演讲

笔者是清华在读研究生&#xff0c;主要关注人形机器人、具身智能。将持续分享行业前沿动态、学者观点整理、论文阅读笔记、知识学习路线等。欢迎交流 最近听了宋老师的演讲&#xff0c;以下是学习整理。部分图截自直播&#xff0c;若模糊望见谅 演讲信息&#xff1a; 【会议】…

Python | Leetcode Python题解之第365题水壶问题

题目&#xff1a; 题解&#xff1a; class Solution:def canMeasureWater(self, x: int, y: int, z: int) -> bool:if x y < z:return Falseif x 0 or y 0:return z 0 or x y zreturn z % math.gcd(x, y) 0