狀態(tài)模式代碼原型
解決的問題:
主要解決的是當(dāng)控制一個(gè)對象狀態(tài)轉(zhuǎn)換的條件表達(dá)式過于復(fù)雜時(shí)的情況。把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同的一系列類當(dāng)中,可以把復(fù)雜的邏輯判斷簡單化。
模式中的角色
1 上下文環(huán)境(Context):它定義了客戶程序需要的接口并維護(hù)一個(gè)具體狀態(tài)角色的實(shí)例,將與狀態(tài)相關(guān)的操作委托給當(dāng)前的Concrete State對象來處理。
2 抽象狀態(tài)(State):定義一個(gè)接口以封裝使用上下文環(huán)境的的一個(gè)特定狀態(tài)相關(guān)的行為。
3 具體狀態(tài)(Concrete State):實(shí)現(xiàn)抽象狀態(tài)定義的接口。
狀態(tài)模式原型代碼的實(shí)現(xiàn):
using UnityEngine;
public class StateDesi : MonoBehaviour
{
private void Start()
{
Context context = new Context();
context.SetState(new ConcreteStateA(context));
context.ContextHandle(5);
context.ContextHandle(20);
context.ContextHandle(30);
context.ContextHandle(4);
}
}
//狀態(tài)的擁有者
public class Context
{
private IState mState;
public void SetState(IState state)
{
mState = state;
}
public void ContextHandle( int arg)
{
mState.Handle(arg);
}
}
public interface IState
{
//處理當(dāng)前狀態(tài)的行為
void Handle(int arg);
}
public class ConcreteStateA : IState
{
private Context mContext;
public ConcreteStateA(Context context)
{
mContext = context;
}
public void Handle(int arg)
{
Debug.Log("ConcreteStateA.Handle"+arg);
if (arg > 10)
{
mContext.SetState(new ConcreteStateB(mContext));
}
}
}
public class ConcreteStateB : IState
{
private Context mContext;
public ConcreteStateB(Context context)
{
mContext = context;
}
public void Handle(int arg)
{
Debug.Log("ConcreteStateB.Handle" + arg);
if (arg <= 10)
{
mContext.SetState(new ConcreteStateA(mContext));
}
}
}
輸出結(jié)果:
首先設(shè)置的初始狀態(tài)是ConcreteStateA,然后然后判斷arg是否大于10,如果大于10就切換到ConcreteStateB狀態(tài),到達(dá)ConcreteStateB狀態(tài)后每次有判斷arg是否小于等于10,如果小于等于又切換到ConcreteStateA狀態(tài),這就是狀態(tài)直接的相互切換。

場景狀態(tài)跳轉(zhuǎn)栗子
下面我舉例子來實(shí)現(xiàn)狀態(tài)模式下場景狀態(tài)的跳轉(zhuǎn),首先來看看,下面有三個(gè)場景狀態(tài),首先是開始界面,顯示完Logo后馬上跳轉(zhuǎn)到游戲主界面場景狀態(tài),點(diǎn)擊開始游戲有跳轉(zhuǎn)到戰(zhàn)斗場景狀態(tài)

創(chuàng)建三個(gè)場景分別命名為StartScene,MainScene,BattleScene。在StartScene場景里創(chuàng)建 GameLoop 游戲?qū)ο?,并在其上掛載GameLoop腳本.

using UnityEngine;
public class GameLoop : MonoBehaviour {
private SceneStateController controller=null;
public void Awake()
{
DontDestroyOnLoad(this.gameObject);//跳轉(zhuǎn)場景也不刪除此游戲?qū)ο? }
// Use this for initialization
void Start () {
controller = new SceneStateController();
controller.SetState(new StartState(controller),false);//設(shè)置默認(rèn)狀態(tài)(初始狀態(tài))
}
// Update is called once per frame
void Update () {
controller.StateUpdate();
}
}
然后就是創(chuàng)建狀態(tài)擁有者SceneController腳本
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneStateController
{
private ISceneState mState;
private AsyncOperation mAO;
//控制StateStart只調(diào)用一次
private bool mIsRunStart = false;
public void SetState(ISceneState state, bool isLpadScene=true)
{
if (mState != null)//如果當(dāng)前有狀態(tài)
{
mState.StateEnd();//讓上一個(gè)場景狀態(tài)做清理工作
}
mState = state;//設(shè)置狀態(tài)
//isLpadScene是否需要加載場景,因?yàn)樽铋_始的場景是不需要加載的
if (isLpadScene)
{
mAO = SceneManager.LoadSceneAsync(mState.SceneName);
mIsRunStart = false;
}
else
{
mState.StateStart();
mIsRunStart = true;
}
}
public void StateUpdate()
{
//正在加載場景的時(shí)候
if (mAO != null && mAO.isDone == false) return;
//場景加載完成 mAO.isDone == true如果場景加載完成才調(diào)用StateStart方法
if (mIsRunStart==false&&mAO != null && mAO.isDone == true)
{
mState.StateStart();
mIsRunStart = true;
}
if (mState != null)
{
mState.StateUpdata();//場景狀態(tài)下每幀更新
}
}
}
下面就是各個(gè)狀態(tài)的基類,
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; }
}
//每次進(jìn)入這個(gè)狀態(tài)的時(shí)候調(diào)用
public virtual void StateStart() { }
//這個(gè)狀態(tài)下每幀更新
public virtual void StateUpdata(){}
//退出這個(gè)狀態(tài)的時(shí)候調(diào)用
public virtual void StateEnd() { }
}
下面是三個(gè)場景狀態(tài)類繼承ISceneState
using UnityEngine;
using UnityEngine.UI;
public class StartState : ISceneState
{
public StartState(SceneStateController controller) : base("StartScene", controller)
{
}
private Image mLogo;
private float mSmoothingTime = 0.5f;
private float mWaitTime = 2;
public override void StateStart()
{
mLogo = GameObject.Find("Logo").GetComponent<Image>();//查找開始面板
mLogo.color = Color.black;//初始設(shè)置為黑色
}
public override void StateUpdata()
{
mLogo.color = Color.Lerp(mLogo.color,Color.white, mSmoothingTime*Time.deltaTime);//從黑色跳轉(zhuǎn)到白色
mWaitTime -= Time.deltaTime;
if (mWaitTime<=0)//兩秒后跳轉(zhuǎn)到第二個(gè)場景
{
mController.SetState(new MainState(mController));
}
}
}
using UnityEngine;
using UnityEngine.UI;
public class MainState : ISceneState
{
public MainState(SceneStateController controller) : base("MainScene", controller)
{
}
public override void StateStart()
{
GameObject.Find("StartButton").GetComponent<Button>().onClick.AddListener(OnClick); ;//給Button注冊按鈕事件
}
private void OnClick()
{
mController.SetState(new BattleState(mController));//跳轉(zhuǎn)到第三個(gè)場景
}
}
public class BattleState : ISceneState
{
public BattleState( SceneStateController controller) : base("BattleScene", controller)
{
}
}

外觀模式
外觀模式定義:
為子系統(tǒng)中的一組接口提供一個(gè)統(tǒng)一的入口。外觀模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。
概述:
外觀模式通過引入一個(gè)外觀角色來簡化客戶端與子系統(tǒng)之間的交互,為復(fù)雜的子系統(tǒng)調(diào)用提供一個(gè)統(tǒng)一的入口,降低子系統(tǒng)與客戶端的耦合度,且客戶端調(diào)用非常方便。
外觀模式實(shí)現(xiàn):
外觀模式通過引入一個(gè)新的外觀類(Facade)來實(shí)現(xiàn)該功能,外觀類充當(dāng)了軟件系統(tǒng)中的“服務(wù)員”,它為多個(gè)業(yè)務(wù)類的調(diào)用提供了一個(gè)統(tǒng)一的入口,簡化了類與類之間的交互。在外觀模式中,那些需要交互的業(yè)務(wù)類被稱為子系統(tǒng)(Subsystem)。如果沒有外觀類,那么每個(gè)客戶類需要和多個(gè)子系統(tǒng)之間進(jìn)行復(fù)雜的交互,系統(tǒng)的耦合度將很大,如圖2(A)所示;而引入外觀類之后,客戶類只需要直接與外觀類交互,客戶類與子系統(tǒng)之間原有的復(fù)雜引用關(guān)系由外觀類來實(shí)現(xiàn),從而降低了系統(tǒng)的耦合度,如圖2(B)所示。
外觀模式中,一個(gè)子系統(tǒng)的外部與其內(nèi)部的通信通過一個(gè)統(tǒng)一的外觀類進(jìn)行,外觀類將客戶類與子系統(tǒng)的內(nèi)部復(fù)雜性分隔開,使得客戶類只需要與外觀角色打交道,而不需要與子系統(tǒng)內(nèi)部的很多對象打交道。
代碼實(shí)現(xiàn)
class SubSystemA
{
public void MethodA()
{
//業(yè)務(wù)實(shí)現(xiàn)代碼
}
}
class SubSystemB
{
public void MethodB()
{
//業(yè)務(wù)實(shí)現(xiàn)代碼
}
}
class SubSystemC
{
public void MethodC()
{
//業(yè)務(wù)實(shí)現(xiàn)代碼
}
}
class Facade
{
private SubSystemA obj1 = new SubSystemA();
private SubSystemB obj2 = new SubSystemB();
private SubSystemC obj3 = new SubSystemC();
public void Method()
{
obj1.MethodA();
obj2.MethodB();
obj3.MethodC();
}
}
class Program
{
static void Main(string[] args)
{
Facade facade = new Facade();
facade.Method();
}
}
借鑒自:
深入淺出外觀模式
設(shè)計(jì)模式學(xué)習(xí)筆記-狀態(tài)模式
單例模式:
http://blog.csdn.net/carson_ho/article/details/52223097
http://blog.csdn.net/iblade/article/details/51107308
設(shè)計(jì)模式之中介者模式(Mediator):
http://www.cnblogs.com/BeyondAnyTime/archive/2012/08/30/2663922.html