我们先设计一个场景,饮料自动售卖机,来设计一下它的出售流程。

流程图中,我们可把这个过程看成几个状态: 投币状态,选择饮料状态,售出状态,出售完毕状态.

,有了这个四个状态,我们设计一下界面(很粗略):

在这里我们只定义了三种饮料和一个投币口,在设计接口和类之前,我们来看一下状态模式的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; }
}
}

创建获取某种饮料的工厂:

 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;
}
}

饮料的存储库

 public class SoftDrinkRepository
{ static SoftDrinkRepository()
{
SoftDrinks = new List<SoftDrink>();
AddSoftDrink(new SoftDrink { Name = "可乐", Count = , Price = });
AddSoftDrink(new SoftDrink { Name = "果粒橙", Count = , Price = });
AddSoftDrink(new SoftDrink { Name = "咖啡", Count = , Price = });
} 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);
}
}

这里存钱的地方,相当于一个银行,用的是静态

  public class Constants
{
public static int StoredMoney { get; set; }
}

接口:

 public interface ISoftdrinkState
{
void InsertQuarter();
void SelectSoftdrink(SoftDrink softDrink);
void Dispense(SoftDrink softDrink);
void SoldOut();
}

这里的四个实现类代表四种状态,整个状态切换由内部自动完成.

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.SetState(softDrink.Count > 0
? _softdrinkMachineContext.NoQuarterState
: _softdrinkMachineContext.SoldOutState);
} public override void SoldOut()
{
throw new InvalidOperationException("请点击选择完毕按");
}
} public class SoldOutState : AbstractSoftdrinkMacheState
{
public SoldOutState(SoftdrinkMachineContext softdrinkMachineContext)
: base(softdrinkMachineContext)
{
} public override void InsertQuarter()
{ } 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("已经售完");
}
}

上下文Context

public class SoftdrinkMachineContext
{
private ISoftdrinkState _state; public SoftdrinkMachineContext()
{
NoQuarterState = new NoQuarterState(this);
SoldOutState = new SoldOutState(this);
HasQuarterState = new HasQuarterState(this);
SoldState = new SoldState(this); _state = NoQuarterState;
} public ISoftdrinkState SoldOutState { get; private set; }
public ISoftdrinkState NoQuarterState { get; private set; }
public ISoftdrinkState HasQuarterState { get; private set; }
public ISoftdrinkState SoldState { get; private set; } public void InsertQuarter()
{
_state.InsertQuarter(); } public void SelectSoftdrink(SoftDrink softDrink)
{
_state.SelectSoftdrink(softDrink);
} public void Dispense(SoftDrink softDrink)
{
_state.Dispense(softDrink);
} public void SoldOut()
{
_state.SoldOut();
} public void SetState(ISoftdrinkState state)
{
_state = state;
}
}

Form窗口类

public partial class Form1 : Form
{
private SoftDrink _currSoftDrink; public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
ActionWithAlertingErrorInfo(() =>
{
_currSoftDrink.Context.Dispense(_currSoftDrink);
MessageBox.Show(string.Format("退出{0}钱", Constants.StoredMoney));
Constants.StoredMoney = ;
}); } private void btnInputMoney_Click(object sender, EventArgs e)
{
var money = ;
if (int.TryParse(txtMoneyInput.Text, out money))
{
Constants.StoredMoney += money;
ActionWithAlertingErrorInfo(() => SoftDrinkRepository.SoftDrinks.ForEach(c => c.Context.InsertQuarter()));
}
} private void btnCoke_Click(object sender, EventArgs e)
{
var btn = sender as Button;
var index = btn.Text.IndexOf("(", StringComparison.Ordinal);
var softDrinkName = btn.Text.Substring(, index); _currSoftDrink = SoftDrinkFactory.GetSoftDrink(softDrinkName); ActionWithAlertingErrorInfo(() => _currSoftDrink.Context.SelectSoftdrink(_currSoftDrink));
} public void ActionWithAlertingErrorInfo(Action action)
{
try
{
action.Invoke();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

这里加入了一个Softdrink类,因为由于每一种饮料都有自己的状态,所以对每个饮料都要有一个上下文的类。

后记:

最近一个朋友告诉我,她怎么都觉得策略模式和状态模式是一样,既然名字不一样,功能肯定不一样,该去怎么区分。

策略模式和状态模式可以说是同胞兄弟,但是本质还是有些区别.

  策略模式->定义算法族,分别封装起来,让它们之间可以互相替换(手动),此模式让算法的变化独立于使用算法的客户。

  状态模式->允许对象在内部状态改变时改变它的行为(自动),对象看来好像修改了它的类。

也就是说,状态模式利用许多不同的状态对象,当Context对象随着时间而改变装,而任何的状态改变都是定义好的。换句话说,“改变行为”这件事是建立在我状态模式自己方案中的,而策略模式并没有一组状态标记,而更多由调用者去使用。

【状态模式】 State Pattern的更多相关文章

  1. 二十四种设计模式:状态模式(State Pattern)

    状态模式(State Pattern) 介绍允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它所属的类. 示例有一个Message实体类,对它的操作有Insert()和Get()方法, ...

  2. 乐在其中设计模式(C#) - 状态模式(State Pattern)

    原文:乐在其中设计模式(C#) - 状态模式(State Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 状态模式(State Pattern) 作者:webabcd 介绍 允 ...

  3. 状态模式-State Pattern(Java实现)

    状态模式-State Pattern 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. State接口 ...

  4. 设计模式(十二):通过ATM取款机来认识“状态模式”(State Pattern)

    说到状态模式,如果你看过之前发布的重构系列的文章中的<代码重构(六):代码重构完整案例>这篇博客的话,那么你应该对“状态模式”并不陌生,因为我们之前使用到了状态模式进行重构.上一篇博客我们 ...

  5. 十一个行为模式之状态模式(State Pattern)

    定义: 当一个对象有多个状态,并且在每个状态下有不同的行为,可以使用状态模式来在其内部改变状态时改变其行为,而客户端不会察觉状态的改变,仍使用同样的方法或接口与对象进行交互. 结构图: Context ...

  6. 【UE4 设计模式】状态模式 State Pattern

    概述 描述 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类. 其别名为状态对象(Objects for States),状态模式是一种对象行为型模式. 有限状态机(FSMs) ...

  7. 状态模式(State Pattern)

    当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂 ...

  8. C#设计模式——状态模式(State Pattern)

    一.概述在面向对象软件设计时,常常碰到某一个对象由于状态的不同而有不同的行为.如果用if else或是switch case等方法处理,对象操作及对象的状态就耦合在一起,碰到复杂的情况就会造成代码结构 ...

  9. [设计模式] 20 状态模式 State Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对状态模式是这样说的:允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类.状态模式的重点在于状态转换,很多时候,对 ...

  10. php状态模式(state pattern)

    ... <?php /* The state pattern encapsulates the varying behavior for the same object based on its ...

随机推荐

  1. 通过js看类似C#中的回掉

    我认为并行有两种形式,第一种是异步,第二种是多线程,目的都是为了实现并行,只不过异步和多线程都是手段而已 第一种异步 异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过 ...

  2. [译] 一、为何要推出AppCoda系列?

    声明:本文翻译自AppCoda网站的文章:Why Launching AppCoda?,作者是创建者Simon Ng.如有异议,请联系博主. 去年九月份,我在App Store上发布了自己第一个iPh ...

  3. iOS10 CoreData新特性

    原文地址:What's New in Core Data in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0 翻译者:肖品,原创文章转载请著名出处 ...

  4. solr集成mmseg4j分词

    solr集成mmseg4j分词 mmseg4j https://code.google.com/p/mmseg4j/ https://github.com/chenlb/mmseg4j-solr 作者 ...

  5. 最近想上游戏,弄了个工作室,名"柑谷工作室"

    最近想上游戏,弄了个工作室,名"柑谷工作室",名字取得有点随便,原因是好名字都让狗用了.想当年我用的龙纹工作室,现在龙纹两字也被人用了.人家有硅谷,然后我弄个柑谷,差不多吧.算了, ...

  6. Qt编写自定义控件大全

    最新版可执行文件 http://pan.baidu.com/s/1i491FQP 不定期增加控件及修正BUG和改进算法. 总图: 1:动画按钮 * 1:可设置显示的图像和底部的文字 * 2:可设置普通 ...

  7. C头文件和源文件的连

    (http://blog.163.com/yui_program/blog/static/18415541520115177852896/) 一.源文件如何根据#include来关联头文件 1,系统自 ...

  8. Exploring Ionic Lists

    Infinite Lists 由于手机不适合使用多页面显示posts,Infinite Lists成为各种新闻.咨询类app的标配.为了在ionic框架中使用到Infinite Lists,我们首先学 ...

  9. There is an internal error in the React performance measurement code.Did not expect componentDidMount timer to start while render timer is still in progress for another instance

    一.There is an internal error in the React performance measurement code.Did not expect componentDidMo ...

  10. 条件注释判断浏览器<!--[if !IE]><!--[if IE]><!--[if lt IE 6]><!--[if gte IE 6]>

    <!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]--><!--[if IE]> 所有的IE可识别 <![e ...