设计模式学习之路(三) ------ 状态模式(State)

  • 学习网址:http://www.cnblogs.com/wangjq/archive/2012/07/16/2593485.html
UML类图:

原型的实现:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DM01Sate : MonoBehaviour
{
    void Start()
    {
        Context context = new Context(); //状态拥有着初始化

        context.SetState(new ConcreteStateA(context)); //设置当前的状态,并设置状态的context

        context.Handle(5);
        context.Handle(20);
        context.Handle(30);
        context.Handle(4);
        context.Handle(6);
    }
}
//Context:状态的拥有者
public class Context
{
    private IState mState;
    //设置context当前的状态
    public void SetState(IState state)
    {
        mState = state;
    }
    //调用context当前的状态的处理方法
    public void Handle(int arg)
    {
        mState.Handle(arg);
    }
}

public interface IState
{
    void Handle(int arg); //处理当前状态的行为,放在IState里面,子类重写以实现不同的状态对应不同的行为
}

public class ConcreteStateA : IState
{
    private Context mContext;
    //构造函数初始化时设置context
    public ConcreteStateA(Context context)
    {
        mContext = context;
    }

    public void Handle(int arg)
    {
        Debug.Log("ConcreateStateA.Handle " + arg);
        if (arg > 10)
        {
            mContext.SetState(new ConcreteStateB(mContext));   //转换状态,因此需要拥有context
        }
    }
}

public class ConcreteStateB : IState
{
    private Context mContext;
    public ConcreteStateB(Context context)
    {
        mContext = context;
    }

    public void Handle(int arg)
    {
        Debug.Log("ConcreateStateB.Handle " + arg);
        if (arg <= 10)
        {
            mContext.SetState(new ConcreteStateA(mContext));
        }
    }
}

应用实例:根据状态切换场景

                                               

UML类图:

          

GameLoop类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameLoop : MonoBehaviour {

    private SceneStateController controller = null; //持有SceneStateController 类

    void Awake()
    {
        DontDestroyOnLoad(this.gameObject);

    }

	// Use this for initialization
	void Start () {
          controller = new SceneStateController();
          controller.SetState(new StartState(controller),false); //设置初始化
	}
	
	// Update is called once per frame
	void Update () {
        if(controller!=null)
            controller.StateUpdate(); //会调用当前状态的更新方法
	}
}

ISceneState类:

using System;
using System.Collections.Generic;
using System.Text;

/// <summary>
/// 状态父类
/// </summary>
public class ISceneState
{
    private string mSceneName; //场景的名字,根据名字来切换
    protected SceneStateController mController;//状态的拥有者

    public ISceneState(string sceneName,SceneStateController controller)
    {
        mSceneName = sceneName;
        mController = controller;
    }

    public string SceneName
    {
        get { return mSceneName; }
    }
    //每次进入到这个状态的时候调用,子类重写
    public virtual void StateStart() { }
    public virtual void StateEnd() { }
    public virtual void StateUpdate(){}
}

SceneStateController类(状态持有类):

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine.SceneManagement;
using UnityEngine;

public class SceneStateController //场景状态管理者,相当于Context
{
    private ISceneState mState; //持有状态
    private AsyncOperation mAO; //异步加载的返回值
    private bool mIsRunStart = false; //是否运行过StateStart方法

    public void SetState(ISceneState state,bool isLoadScene=true) //isLoadScene是否需要加载场景,默认是需要的.这个参数是由于初始场景是不需要加载场景的
    {
        if (mState != null)
        {
            mState.StateEnd();//让上一个场景状态做一下清理工作
        }
        mState = state; //设置成新的状态
        if (isLoadScene)
        {
            mAO = SceneManager.LoadSceneAsync(mState.SceneName);//异步加载场景,后面不能立马执行StateStart方法,因为场景有可能还没有加载成功
            mIsRunStart = false;
        } else
        {
            mState.StateStart();
            mIsRunStart = true;
        }
        
    }

    public void StateUpdate()
    {
        if (mAO != null && mAO.isDone == false) return; //判断当前是否还在异步加载场景

        if (mIsRunStart==false && mAO != null && mAO.isDone == true)
        {
            mState.StateStart(); //场景加载完成调用StateStart方法
            mIsRunStart = true; //控制只需要调用一次
        }
        //当前状态不为空 调用更新
        if (mState != null)
        {
            mState.StateUpdate();
        }
    }
}

StartState类(开始场景类):

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine.UI;
using UnityEngine;

public class StartState:ISceneState //开始场景类
{
    //构造方法
    public StartState(SceneStateController controller):base("01StartScene",controller)
    {
    }

    private Image mLogo;
    private float mSmoothingSpeed = 1;
    private float mWaitTime = 2; //动画的时间

    public override void StateStart()
    {
        //显示Logo
        mLogo = GameObject.Find("Logo").GetComponent<Image>();
        mLogo.color = Color.black;
    }

    public override void StateUpdate()
    {
        mLogo.color = Color.Lerp(mLogo.color, Color.white, mSmoothingSpeed * Time.deltaTime); //Logo的动画
        mWaitTime -= Time.deltaTime; 
        if (mWaitTime <= 0)
        {
            mController.SetState(new MainMenuState(mController)); //状态跳转
        }
    }
}

MainMenuState类(菜单场景):

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;


public class MainMenuState:ISceneState
{
    public MainMenuState(SceneStateController controller) : base("02MainMenuScene", controller) { }

    public override void StateStart()
    {
        GameObject.Find("StartButton").GetComponent<Button>().onClick.AddListener(OnStartButtonClick);//按钮注册事件
    }
    private void OnStartButtonClick()
    {
        mController.SetState(new BattleState(mController)); //切换到战斗场景
    }
}

BattleState类(战斗场景):

using System;
using System.Collections.Generic;
using System.Text;


public class BattleState:ISceneState
{
    public BattleState(SceneStateController controller):base("03BattleScene",controller)
    {}
    //兵营  关卡 角色管理 行动力 成就系统。。。

    public override void StateStart()
    {
        GameFacade.Insance.Init();
    }
    public override void StateEnd()
    {
        GameFacade.Insance.Release();
    }
    public override void StateUpdate()
    {
        if (GameFacade.Insance.isGameOver)
        {
            mController.SetState(new MainMenuState(mController));
        }

        GameFacade.Insance.Update();
    }
}


猜你喜欢

转载自blog.csdn.net/dengshunhao/article/details/80645935