来说说指令(Command)模式

本文探讨了指令模式在软件设计中的作用,强调它如何实现请求发送者与执行者的解耦,提升系统灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.指令模式的意义。
模式是为了解决问题而生,他让编程流程化,面相对象话,系统模块话,让人易于读,易于写,易于扩展,易于修改,软件逻辑,尤其复杂点的游戏世界,它的逻辑更是千奇百遍,策划的思路有时候更是天马行空。所以为了解决这些问题,人们约定俗成了一样设计思路,即设计模式。但是也不能一味的套用设计模式,他也同时只是一种思想,跟古代的兵法一样,虚虚实实,伺机而动。而今天所说的指令模式,其实说白了就是对指令的一种封装,用人们常说的一句话就是,指令就像餐厅里面的菜单一样,顾客到餐厅里面点餐,服务员一一给顾客介绍各种美味的凉菜,热菜,饮料等等。然后顾客决定我要吃凉拌黄瓜,农家小炒肉,还有一杯扎啤,然后服务员就给顾客下订单了,像厨房pos机器发送指令了,A指令:发给凉菜师傅,让凉菜师傅做凉拌黄瓜,B指令:发给热菜师傅,做农家小炒肉,C指令:发给一个服务员,弄一杯扎啤。这样就形成了完整的指令模式。
在我们的游戏设计中,如ACT格斗游戏中,我们可以用指令模式来设计各种操作的交互,我们可以把普工,技能攻击,跑,跳,等操作封装为command命令,当玩家操纵遥感的时候,就可以像操作对象来发送各种指令,我们可以通过一个Invoke的路由器来管理这些指令,在时候的时候执行这些命令,我们来封装一个简单的指令接口。
using System;
using UnityEngine;

public interface CommandBase
{
	void execute(GameObject gameObjects);
	void unexecute(GameObject gameObjects);
}
这是一个指令的接口,他的基类必须要实现这2个方法,这两个方法主要是提供给路由器也就是Invoke服务员,让他等待顾客下完订单之后,她在生成命令,在调用execute方法来执行命令,如果客人反悔了怎么办,就调用unexecute 来撤销订单。我们在来实现一个命令的接口,如下实现一个移动的命令,继承自CommandBase
public class MoveCommand : CommandBase
{
	public void execute(GameObject gameObjects)
	{
		Debug.Log ("我在移动+++++++++++++++++++");
	}
	public void unexecute(GameObject gameObjects)
	{
		Debug.Log ("我要移动回去+++++++++++++++++++");
	}
}
这是一个完整的基本的移动command,即当Invoker来执行命令的时候,移动command就会调用 GameObject 的移动方法来进行移动。当撤销的时候,就可以调用unexecute 方法来进行移动回去等,这些具体的实现需要根据你的业务逻辑来进行实现。同理,我们来实现一个攻击命令。
using System;
using UnityEngine;

public class AttackCommand : CommandBase
{
	public void execute(GameObject gameObjects)
	{
		Debug.Log ("我要攻击你,攻击你+++++++++++++");
	}
	public void unexecute(GameObject gameObjects)
	{
		Debug.Log ("我不攻击你了,我要撤回去,++++++++++++");
	}
}
好了,我们已经实现了两个最简单的大概的命令,我们来实现invoker方法。
using System;
using System.Collections.Generic;
using UnityEngine;

//命令的队列 命令的发送者我给成一个单例  到底应不应该是个单利 这个根据业务逻辑来定义了
public class CommandInvoke
{
	public GameObject m_GameObejects;
	private CommandBase m_BackCommand;

	Queue<CommandBase > comandList = new Queue<CommandBase> ();

	public void setComamnd(CommandBase comandBase,GameObject riverObejcts)
	{
		m_GameObejects = riverObejcts;
		comandList.Enqueue(comandBase);
	}

	//执行命令  执行完成之后在看队列里面还有没有命令 没有命令则继续执行
	public void execute()
	{
		if (comandList.Count > 0) 
		{	
			foreach(var commands in comandList )
			{
				m_BackCommand = commands;
				commands.execute (m_GameObejects);
			}
		}
		comandList.Clear ();
	}

	/// <summary>
	/// 撤销方法
	/// </summary>
	public void UnDone()
	{
		m_BackCommand.unexecute (m_GameObejects);
	}
}

这个方法其实也很简单,就是用来管理命令的,还是根据你的逻辑来进行编写,你可以写一个队列,把玩家操作的命令都添加到队列里面去,执行完一个在执行下一个,或者都同时执行,等等。看看简不简单了。我们来实现一个测试的方法。
using System;
using UnityEngine;
using UnityEngine.UI;

public class TestComand :MonoBehaviour
{
	public GameObject m_GameObjects;
	private CommandInvoke m_Invoke;
	void Start()
	{
		m_Invoke = new CommandInvoke ();
	}
		
	public void BtnClickMove()
	{
		CommandBase moveComand = new MoveCommand ();
		m_Invoke.setComamnd (moveComand,m_GameObjects);
		m_Invoke.execute ();
	}

	public void BtnClickAttack()
	{
		CommandBase sclaeCommands = new AttackCommand ();
		m_Invoke.setComamnd (sclaeCommands,m_GameObjects);
		m_Invoke.execute ();
	}
}

这样,就可以根据玩家不同的操作来发送不同的指令,同时在Invoker里面来管理这些指令。是不是很简单啊,这样你也就完全不用关心接收者了,只用来组装自己的命令,发送命令,重点在于要解耦“请求的发送者”和“请求的执行者”。
  1. 重点在于要解耦“请求的发送者”和“请求的执行者”


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值