我们先设计一个场景,饮料自动售卖机,来设计一下它的出售流程。
流程图中,我们可把这个过程看成几个状态: 投币状态,选择饮料状态,售出状态,出售完毕状态.
,有了这个四个状态,我们设计一下界面(很粗略):
在这里我们只定义了三种饮料和一个投币口,在设计接口和类之前,我们来看一下状态模式的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
新闻热点
疑难解答