狀態模式旨在容許對象在其內部狀態改變時改變其自身行爲。git
咱們以烤牛排爲例,生熟程度分爲:github
簡單來講就是從生到熟的幾個檔次。ide
抽象的狀態類:ui
/// <summary> /// The State abstract class /// </summary> abstract class Doneness { protected Steak steak; protected double currentTemp; protected double lowerTemp; protected double upperTemp; protected bool canEat; public Steak Steak { get { return steak; } set { steak = value; } } public double CurrentTemp { get { return currentTemp; } set { currentTemp = value; } } public abstract void AddTemp(double temp); public abstract void RemoveTemp(double temp); public abstract void DonenessCheck(); }
具體的狀態類:this
/// <summary> /// A Concrete State class. /// </summary> class Uncooked : Doneness { public Uncooked(Doneness state) { currentTemp = state.CurrentTemp; steak = state.Steak; Initialize(); } private void Initialize() { lowerTemp = 0; upperTemp = 130; canEat = false; } public override void AddTemp(double amount) { currentTemp += amount; DonenessCheck(); } public override void RemoveTemp(double amount) { currentTemp -= amount; DonenessCheck(); } public override void DonenessCheck() { if (currentTemp > upperTemp) { steak.State = new Rare(this); } } } /// <summary> /// A 'ConcreteState' class. /// </summary> class Rare : Doneness { public Rare(Doneness state) : this(state.CurrentTemp, state.Steak) { } public Rare(double currentTemp, Steak steak) { this.currentTemp = currentTemp; this.steak = steak; canEat = true; //We can now eat the steak Initialize(); } private void Initialize() { lowerTemp = 130; upperTemp = 139.999999999999; canEat = true; } public override void AddTemp(double amount) { currentTemp += amount; DonenessCheck(); } public override void RemoveTemp(double amount) { currentTemp -= amount; DonenessCheck(); } public override void DonenessCheck() { if (currentTemp < lowerTemp) { steak.State = new Uncooked(this); } else if (currentTemp > upperTemp) { steak.State = new MediumRare(this); } } } /// <summary> /// A Concrete State class /// </summary> class MediumRare : Doneness { public MediumRare(Doneness state) : this(state.CurrentTemp, state.Steak) { } public MediumRare(double currentTemp, Steak steak) { this.currentTemp = currentTemp; this.steak = steak; canEat = true; Initialize(); } private void Initialize() { lowerTemp = 140; upperTemp = 154.9999999999; } public override void AddTemp(double amount) { currentTemp += amount; DonenessCheck(); } public override void RemoveTemp(double amount) { currentTemp -= amount; DonenessCheck(); } public override void DonenessCheck() { if (currentTemp < 0.0) { steak.State = new Uncooked(this); } else if (currentTemp < lowerTemp) { steak.State = new Rare(this); } else if (currentTemp > upperTemp) { steak.State = new Medium(this); } } } /// <summary> /// A Concrete State class /// </summary> class Medium : Doneness { public Medium(Doneness state) : this(state.CurrentTemp, state.Steak) { } public Medium(double currentTemp, Steak steak) { this.currentTemp = currentTemp; this.steak = steak; canEat = true; Initialize(); } private void Initialize() { lowerTemp = 155; upperTemp = 169.9999999999; } public override void AddTemp(double amount) { currentTemp += amount; DonenessCheck(); } public override void RemoveTemp(double amount) { currentTemp -= amount; DonenessCheck(); } public override void DonenessCheck() { if (currentTemp < 130) { steak.State = new Uncooked(this); } else if (currentTemp < lowerTemp) { steak.State = new MediumRare(this); } else if (currentTemp > upperTemp) { steak.State = new WellDone(this); } } } /// <summary> /// A Concrete State class /// </summary> class WellDone : Doneness //aka Ruined { public WellDone(Doneness state) : this(state.CurrentTemp, state.Steak) { } public WellDone(double currentTemp, Steak steak) { this.currentTemp = currentTemp; this.steak = steak; canEat = true; Initialize(); } private void Initialize() { lowerTemp = 170; upperTemp = 230; } public override void AddTemp(double amount) { currentTemp += amount; DonenessCheck(); } public override void RemoveTemp(double amount) { currentTemp -= amount; DonenessCheck(); } public override void DonenessCheck() { if (currentTemp < 0) { steak.State = new Uncooked(this); } else if (currentTemp < lowerTemp) { steak.State = new Medium(this); } } }
上下文類-牛排:spa
/// <summary> /// The Context class /// </summary> class Steak { private Doneness _state; private string _beefCut; public Steak(string beefCut) { _cook = beefCut; _state = new Rare(0.0, this); } public double CurrentTemp { get { return _state.CurrentTemp; } } public Doneness State { get { return _state; } set { _state = value; } } public void AddTemp(double amount) { _state.AddTemp(amount); Console.WriteLine("Increased temperature by {0} degrees.", amount); Console.WriteLine(" Current temp is {0}", CurrentTemp); Console.WriteLine(" Status is {0}", State.GetType().Name); Console.WriteLine(""); } public void RemoveTemp(double amount) { _state.RemoveTemp(amount); Console.WriteLine("Decreased temperature by {0} degrees.", amount); Console.WriteLine(" Current temp is {0}", CurrentTemp); Console.WriteLine(" Status is {0}", State.GetType().Name); Console.WriteLine(""); } }
客戶端調用:.net
static void Main(string[] args) { //Let's cook a steak! Steak account = new Steak("T-Bone"); // Apply temperature changes account.AddTemp(120); account.AddTemp(15); account.AddTemp(15); account.RemoveTemp(10); //Yes I know cooking doesn't work this way, bear with me. account.RemoveTemp(15); account.AddTemp(20); account.AddTemp(20); account.AddTemp(20); Console.ReadKey(); }
狀態模式容許對象的行爲隨着其內部狀態的改變而改變,而且它經過使對象的狀態與對象自己分開來完成這一任務。
所以,狀態能夠爲對象實現它們本身的行爲,而且對象能夠對其內部狀態改變做出「反應」。code
https://github.com/exceptionnotfound/DesignPatterns/tree/master/State對象
https://www.exceptionnotfound.net/state-the-daily-design-pattern/get