來說說指令(Command)模式

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. 重點在於要解耦“請求的發送者”和“請求的執行者”


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章