狀態模式(State),當一個對象的內在狀態改變時,允許改變其行為,這個對象看起來好像改變了其類。狀態模式主要解決的是當控制一個對象的狀態轉換條件表達式過於復雜時的情況。把狀態的判斷邏輯轉移到不同狀態的一系列類中,可以把復雜的判斷邏輯簡化。
狀態模式UML類圖:
分析:由上圖可知(1)State類,抽象狀態類,定義一個接口以封裝與Context的一個特定狀態相關的行為;(2)ConcreteState類,具體狀態,每一個子類實現一個與Context的一個特定狀態相關的行為;(3)Context類,維護一個ConcreteState子類的實例,這個實例定義當前的狀態
狀態模式實現:
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace State
{
/*
* State類,抽象狀態類,定義一個接口以封裝與Context的一個特定狀態相關的行為
*/
abstract class State
{
public abstract void Handle(Context context);
}
/*
* ConcreteState類,具體狀態,每一個子類實現一個與Context的一個特定狀態相關的行為。
*/
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.setState(new ConcreteStateB());//假設ConcreteStateA的下一個狀態是ConcreteStateB
//throw new NotImplementedException();
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.setState(new ConcreteStateA());//假設ConcreteStateB的下一個狀態是ConcreteStateA
//throw new NotImplementedException();
}
}
/*
* Context類,維護一個ConcreteState子類的實例,這個實例定義當前的狀態
*/
class Context
{
private State state;
public Context(State state)
{
this.state = state;
}
public State getState()
{
return this.state;
}
public void setState(State state)
{
this.state = state;
Console.WriteLine("當前狀態:"+this.state.GetType().Name);
}
public void Request()
{
this.state.Handle(this);
}
}
}
客戶端:
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace State
{
//客戶端代碼
class Program
{
static void Main(string[] args)
{
Context context = new Context(new ConcreteStateA());
context.Request();
context.Request();
context.Request();
context.Request();
Console.Read();
}
}
}
狀態模式總結:
(1)狀態模式的好處就是將於特定狀態相關的行為局部化,並且將不同狀態的行為分割開來。意即,將特定的狀態相關的行為都放入一個對象中,由於所有與狀態相關的代碼都存在於某個ConcreteState中,所以通過定義新的子類可以很容易地增加新的狀態和轉換。
(2)這樣做的目的是為了消除龐大的條件分支語句,大的分支判斷會使得它們難以修改和擴展,狀態模式通過把各種狀態轉移邏輯分布到State的子類之間,來減少相互間的依賴。
(3)當一個對象的行為取決於它們的狀態,並且它必須在運行時刻根據狀態改變它的行為時,就可以考慮使用狀態模式。
狀態模式案例—工作狀態
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StateExample
{
/*
* 抽象狀態類
*/
abstract class State
{
public abstract void writeProgram(Work work);
}
/*
* 具狀態類
*/
class ForenoonState : State
{
public override void writeProgram(Work work)
{
if (work.getHour() < 12)
{
Console.WriteLine("當前時間{0},上午狀態,精神百倍!", work.getHour());
}
else
{
work.setState(new NoonState());
work.writeProgram();
}
//throw new NotImplementedException();
}
}
class NoonState : State
{
public override void writeProgram(Work work)
{
if (work.getHour() < 13)
{
Console.WriteLine("當前時間{0},午飯時間!", work.getHour());
}
else
{
work.setState(new AfterNoonState());
work.writeProgram();
}
//throw new NotImplementedException();
}
}
class AfterNoonState : State
{
public override void writeProgram(Work work)
{
if (work.getHour() < 17)
{
Console.WriteLine("當前時間{0},下午狀態,繼續工作!", work.getHour());
}
else
{
work.setState(new EveningState());
work.writeProgram();
}
//throw new NotImplementedException();
}
}
class EveningState : State
{
public override void writeProgram(Work work)
{
if (work.getIsFinish())
{
work.setState(new RestState());
work.writeProgram();
}
else
{
if (work.getHour() < 21)
{
Console.WriteLine("當前時間{0},加班狀態,疲憊!", work.getHour());
}
else
{
work.setState(new SleepState());
work.writeProgram();
}
}
//throw new NotImplementedException();
}
}
class RestState : State
{
public override void writeProgram(Work work)
{
Console.WriteLine("當前時間{0},完成工作,下班回家!",work.getHour());
//throw new NotImplementedException();
}
}
class SleepState : State
{
public override void writeProgram(Work work)
{
Console.WriteLine("當前時間{0},睡覺狀態!", work.getHour());
//throw new NotImplementedException();
}
}
/*
* 工作類
*/
class Work
{
private double hour;
private State state;
private bool isFinish;
public Work(State state)
{
this.state = state;
}
public State getState()
{
return this.state;
}
public void setState(State state)
{
this.state = state;
}
public double getHour()
{
return this.hour;
}
public void setHour(double hour)
{
this.hour = hour;
}
public bool getIsFinish()
{
return this.isFinish;
}
public void setIsFinish(bool b)
{
this.isFinish = b;
}
public void writeProgram()
{
this.state.writeProgram(this);
}
}
}
客戶端:
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StateExample
{
class Program
{
static void Main(string[] args)
{
Work work = new Work(new ForenoonState());
work.setHour(9);
work.writeProgram();
work.setHour(10);
work.writeProgram();
work.setHour(12);
work.writeProgram();
work.setHour(13);
work.writeProgram();
work.setHour(15);
work.writeProgram();
work.setHour(17);
work.writeProgram();
work.setIsFinish(false);
work.setHour(19);
work.writeProgram();
work.setHour(21);
work.writeProgram();
work.setHour(22);
work.writeProgram();
Console.Read();
}
}
}
運行結果: