設計模式2:state pattern
阿新 • • 發佈:2018-12-13
允許一個物件在其內部狀態改變時改變它的行為,物件看起來似乎修改了它的類。
這句黑話,我頭幾次看,不能理解。但當踏踏實實敲一遍程式碼後,有了一點自己的理解: 舉個例子,一個遊戲角色有行走,跳,跑等幾個狀態,我們如何編碼讓遊戲物件從一個狀態到另一個狀態時,行為也自動隨之改變,而之後修改狀態時,無需再來修改高層的類呢。設計模式裡有一個原則,對介面程式設計,不對實現程式設計。如何聯絡物件和物件狀態呢?我們用介面(抽象類,介面,父類,總之一句話,實現執行時多型即可)。
四人幫GOF的設計模式裡有張圖,非常簡潔清晰的說明了問題。
其中Context就是遊戲物件,遊戲物件有一個State型別的遊戲狀態成員,request()方法呼叫State->handle實現功能即可。
測試程式碼
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace HeroineState { public class Heroine{ public void HandleInput() { state.HandleInput(); } public HeroineState NextState() { return state = state.NextState(); } //public HeroineState State { get; set; } private HeroineState state = StandingState.GetStand; } public class HeroineState { //private static StandingState standing; // 如果類是抽象類就只是聲明瞭,其子類例項化 //private static JumpingState jumping; //private static StandingState standing = new StandingState(); // 子類父類共享的欄位. 如果類包含靜態欄位,則提供在類載入時初始化它們的靜態建構函式。或者宣告時直接初始化 public virtual void HandleInput() { } public virtual HeroineState NextState() { return null; } } public class StandingState:HeroineState{ private StandingState() { } private static StandingState standing = new StandingState(); public static StandingState GetStand { get { return standing; } } public float chargeTime = 0; public override void HandleInput() { if(Input.GetButton("Fire123")) Debug.Log("Fire when standing!!"); } public override HeroineState NextState() { if (Input.GetButton("jump")) { Debug.Log("stand to jump"); return JumpingState.GetJump; } else if (Input.GetButton("Stand")) { Debug.Log("keep standing"); return this; } //Debug.Log("No if call"); return this; } } public class JumpingState : HeroineState { private JumpingState() { } private static JumpingState jumping = new JumpingState(); public static JumpingState GetJump { get { return jumping; } } public float chargeTime = 0; public override void HandleInput() { if (Input.GetButton("Fire123")) Debug.Log("Fire when jumping!!"); } public override HeroineState NextState() { if (Input.GetButton("Stand")) { Debug.Log("jump to stand"); return StandingState.GetStand; } else if(Input.GetButton("jump")){ Debug.Log("keep jumping!"); return this; } //Debug.Log("No if call"); return this; } } }