我們先設計一個場景,飲料自動售賣機,來設計一下它的出售流程。

流程圖中,我們可把這個過程看成幾個狀態: 投幣狀態,選擇飲料狀態,售出狀態,出售完畢狀態.
,有了這個四個狀態,我們設計一下界面(很粗略):

在這里我們只定義了三種飲料和一個投幣口,在設計接口和類之前,我們來看一下狀態模式的UML圖:

State接口定義了一個所有具體狀態的共同接口;任何狀態都實現這個相同的接口,這樣一來,狀態之間可以互相代替.
ConcreteState(具體狀態)處理來自Context請求。每一個ConcreteState都提供了它自己對于請求的實現。所以,當Context改變狀態時行為也跟著改變。
Context(上下文)是一個類,它可以擁有一些內部狀態。
根據成熟的狀態模式UML圖,我們來設計我們自己的UML類圖:

直接上代碼(可能和UML圖有些出入,多了些參數,圖主要是搭出一個架構來)
實體類:

public class SoftDrink { public string Name { get; set; } public int PRice { get; set; } public int Count { get; set; } private SoftdrinkMachineContext _context = new SoftdrinkMachineContext(); public SoftdrinkMachineContext Context { get { return _context; } } }View Code創建獲取某種飲料的工廠:

public class SoftDrinkFactory { public static SoftDrink GetSoftDrink(string softDrinkName) { SoftDrink softDrink = SoftDrinkRepository.SoftDrinks.SingleOrDefault(s => s.Name.Equals(softDrinkName)); if (softDrink == null) throw new ArgumentException(string.Format("沒有該飲料:{0}", softDrinkName)); return softDrink; } }View Code飲料的存儲庫

public class SoftDrinkRepository { static SoftDrinkRepository() { SoftDrinks = new List<SoftDrink>(); AddSoftDrink(new SoftDrink { Name = "可樂", Count = 5, Price = 3 }); AddSoftDrink(new SoftDrink { Name = "果粒橙", Count = 1, Price = 3 }); AddSoftDrink(new SoftDrink { Name = "咖啡", Count = 5, Price = 3 }); } public static List<SoftDrink> SoftDrinks { get; private set; } public static void AddSoftDrink(SoftDrink softDrink) { if (SoftDrinks.Any(s => s.Name.Equals(softDrink.Name))) { SoftDrink needtobeAddedSoftdrink = SoftDrinks.Single(s => s.Name.Equals(softDrink.Name)); needtobeAddedSoftdrink.Price = softDrink.Price; needtobeAddedSoftdrink.Count = softDrink.Count; } SoftDrinks.Add(softDrink); } }View Code這里存錢的地方,相當于一個銀行,用的是靜態

public class Constants { public static int StoredMoney { get; set; } }View Code接口:

public interface ISoftdrinkState { void InsertQuarter(); void SelectSoftdrink(SoftDrink softDrink); void Dispense(SoftDrink softDrink); void SoldOut(); }View Code這里的四個實現類代表四種狀態,整個狀態切換由內部自動完成.

public abstract class AbstractSoftdrinkMacheState : ISoftdrinkState { protected SoftdrinkMachineContext _softdrinkMachineContext; protected AbstractSoftdrinkMacheState(SoftdrinkMachineContext softdrinkMachineContext) { _softdrinkMachineContext = softdrinkMachineContext; } public abstract void InsertQuarter(); public abstract void SelectSoftdrink(SoftDrink softDrink); public abstract void Dispense(SoftDrink softDrink); public abstract void SoldOut(); } public class NoQuarterState : AbstractSoftdrinkMacheState { public NoQuarterState(SoftdrinkMachineContext softdrinkMachineContext) : base(softdrinkMachineContext) { } public override void InsertQuarter() { _softdrinkMachineContext.SetState(_softdrinkMachineContext.HasQuarterState); } public override void SelectSoftdrink(SoftDrink softDrink) { throw new InvalidOperationException("你需要先投幣"); } public override void Dispense(SoftDrink softDrink) { throw new InvalidOperationException("你需要先投幣"); } public override void SoldOut() { throw new InvalidOperationException("你需要先投幣"); } } public class HasQuarterState : AbstractSoftdrinkMacheState { public HasQuarterState(SoftdrinkMachineContext softdrinkMachineContext) : base(softdrinkMachineContext) { } public override void InsertQuarter() { } public override void SelectSoftdrink(SoftDrink softDrink) { if (softDrink.Price > Constants.StoredMoney) throw new InvalidOperationException("錢不夠,請重新選擇或補足"); _softdrinkMachineContext.SetState(_softdrinkMachineContext.SoldState); } public override void Dispense(SoftDrink softDrink) { throw new InvalidOperationException("你需要先選擇飲料"); } public override void SoldOut() { throw new InvalidOperationException("你需要先選擇飲料"); } } public class SoldState : AbstractSoftdrinkMacheState { public SoldState(SoftdrinkMachineContext softdrinkMachineContext) : base(softdrinkMachineContext) { } public override void InsertQuarter() { throw new InvalidOperationException("請點擊選擇完畢按"); } public override void SelectSoftdrink(SoftDrink softDrink) { throw new InvalidOperationException("請點擊選擇完畢按"); } public override void Dispense(SoftDrink softDrink) { softDrink.Count--; Constants.StoredMoney -= softDrink.Price; _softdrinkMachineContext.S
新聞熱點
疑難解答