1. 程式人生 > >設計模式2:state pattern

設計模式2:state pattern

允許一個物件在其內部狀態改變時改變它的行為,物件看起來似乎修改了它的類。

這句黑話,我頭幾次看,不能理解。但當踏踏實實敲一遍程式碼後,有了一點自己的理解: 舉個例子,一個遊戲角色有行走,跳,跑等幾個狀態,我們如何編碼讓遊戲物件從一個狀態到另一個狀態時,行為也自動隨之改變,而之後修改狀態時,無需再來修改高層的類呢。設計模式裡有一個原則,對介面程式設計,不對實現程式設計。如何聯絡物件和物件狀態呢?我們用介面(抽象類,介面,父類,總之一句話,實現執行時多型即可)。

四人幫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;
        }
    }


}