[Head First设计模式]生活中学设计模式——状态模式
系列文章
[Head First设计模式]山西面馆中的设计模式——装饰者模式
[Head First设计模式]山西面馆中的设计模式——观察者模式
[Head First设计模式]山西面馆中的设计模式——建造者模式
[Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式
[Head First设计模式]抢票中的设计模式——代理模式
[Head First设计模式]云南米线馆中的设计模式——模版方法模式
[Head First设计模式]餐馆中的设计模式——命令模式
[Head First设计模式]身边的设计模式——适配器模式
[Head First设计模式]生活中学设计模式——迭代器模式
[Head First设计模式]生活中学设计模式——组合模式
[Head First设计模式]生活中学设计模式——外观模式
引言
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
允许一个对象在其内部状态改变时改变它的行为。
状态模式
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
类图

Context:状态管理器,它定义了客户感兴趣的接口,这个接口是由State去实现的;并维护一个ConcreteState子类的实例,这个实例定义当前的状态,当前状态变化的时候,会将变化后的ConcreteState返回给当前状态。
角色
state:状态,定义一个接口以封装与Context的特定状态相关的行为,但是行为本身是空的,该行为是由ConcreteState来实现的。
ConcreteState:具体状态子类,每一个子类实现一个与Contex的一个状态相关的行为。
一个例子
在过马路的时候,交通灯的状态,红,黄,绿,时间到了,在三个状态中切换。现在就用代码进行模拟。
namespace Wolfy.状态模式
{
/// <summary>
/// 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
/// </summary>
public abstract class TrafficLightState
{
/// <summary>
/// 改变状态的方法
/// </summary>
public abstract void ChangeState(TrafficLight context);
}
}
namespace Wolfy.状态模式
{
/// <summary>
/// 具体状态类 绿灯状态
/// </summary>
public class GreenState:TrafficLightState
{
public override void ChangeState(TrafficLight contex)
{
Console.WriteLine("绿灯行");
contex.SetState(new RedState());
}
}
}
namespace Wolfy.状态模式
{
/// <summary>
/// 具体状态类 黄灯状态
/// </summary>
public class YellowState : TrafficLightState
{ public override void ChangeState(TrafficLight contex)
{
Console.WriteLine("黄灯亮了等一等");
//改变状态
contex.SetState(new GreenState());
}
}
}
namespace Wolfy.状态模式
{
/// <summary>
/// 具体状态类 红灯状态
/// </summary>
public class RedState : TrafficLightState
{
public override void ChangeState(TrafficLight contex)
{
Console.WriteLine("红灯停");
//改变状态
contex.SetState(new YellowState());
}
}
}
namespace Wolfy.状态模式
{
/// <summary>
///TrafficLight相当于 Context(上下文)类 拥有一些内部状态
/// </summary>
public class TrafficLight
{
//定时器 为了模拟等待的过程 定义一个定时器
private Timer timer;
//记录状态
private TrafficLightState state;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="time">时间间隔</param>
public TrafficLight(int time)
{
this.timer = new Timer();
this.timer.Start();
this.timer.Elapsed += timer_Elapsed;
this.timer.Interval = time; }
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
this.Request();
}
public void SetState(TrafficLightState state)
{
this.state = state;
}
/// <summary>
/// 对请求做处理,并设置下一个状态
/// </summary>
public void Request()
{
//时间到 改变一次状态
state.ChangeState(this);
}
}
}
测试
namespace Wolfy.状态模式
{
class Program
{
static void Main(string[] args)
{
TrafficLight trafficLight = new TrafficLight();
//初始化第一个状态
trafficLight.SetState(new RedState());
//发送请求 显示第一个状态 不用等待
trafficLight.Request();
Console.Read();
}
}
}
结果
总结
优点
状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开。
State模式将所有与一个特定的状态相关的行为都放入一个对象中。因为所有与状态相关的代码都存在于某一个State子类中, 所以通过定义新的子类可以很容易的增加新的状态和转换。另一个方法是使用数据值定义内部状态并且让 Context操作来显式地检查这些数据。但这样将会使整个Context的实现中遍布看起来很相似的条件if else语句或switch case语句。增加一个新的状态可能需要改变若干个操作, 这就使得维护变得复杂了。State模式避免了这个问题, 但可能会引入另一个问题, 因为该模式将不同状态的行为分布在多个State子类中。这就增加了子类的数目,相对于单个类的实现来说不够紧凑。但是如果有许多状态时这样的分布实际上更好一些, 否则需要使用巨大的条件语句。正如很长的过程一样,巨大的条件语句是不受欢迎的。它们形成一大整块并且使得代码不够清晰,这又使得它们难以修改和扩展。 State模式提供了一个更好的方法来组织与特定状态相关的代码。决定状态转移的逻辑不在单块的 i f或s w i t c h语句中, 而是分布在State子类之间。将每一个状态转换和动作封装到一个类中,就把着眼点从执行状态提高到整个对象的状态。这将使代码结构化并使其意图更加清晰。
它使得状态转换显式化
当一个对象仅以内部数据值来定义当前状态时 , 其状态仅表现为对一些变量的赋值,这不够明确。为不同的状态引入独立的对象使得转换变得更加明确。而且, State对象可保证Context不会发生内部状态不一致的情况,因为从 Context的角度看,状态转换是原子的—只需重新绑定一个变量(即Context的State对象变量),而无需为多个变量赋值
State对象可被共享
如果State对象没有实例变量—即它们表示的状态完全以它们的类型来编码—那么各Context对象可以共享一个State对象。当状态以这种方式被共享时, 它们必然是没有内部状态, 只有行为的轻量级对象。
缺点
导致较多的ConcreteState子类。
适用场景
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式。
一个操作中含有庞大的分支机构,并且这些分支决定于对象的状态。
参考
《Head First 设计模式》
[Head First设计模式]生活中学设计模式——状态模式的更多相关文章
- [Head First设计模式]生活中学设计模式——组合模式
系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...
- [Head First设计模式]生活中学设计模式——外观模式
系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...
- [Head First设计模式]生活中学设计模式——迭代器模式
系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...
- Java设计模式(19)状态模式(State模式)
State的定义:不同的状态,不同的行为:或者说,每个状态有着相应的行为. 何时使用状态模式 State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If else ...
- Javascript设计模式之我见:状态模式
大家好!本文介绍状态模式及其在Javascript中的应用. 模式介绍 定义 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要解决的是控制一个对象状态的条件表达式 ...
- 《Head First 设计模式》学习笔记——状态模式
在软件开发过程中.应用程序可能会依据不同的情况作出不同的处理. 最直接的解决方式是将这些全部可能发生的情况全都考虑到.然后使用if... ellse语句来做状态推断来进行不同情况的处理. 可是对复杂状 ...
- C#设计模式之十九状态模式(State Pattern)【行为型】
一.引言 今天我们开始讲"行为型"设计模式的第六个模式,该模式是[状态模式],英文名称是:State Pattern.无论是现实世界,还是面向对象的OO世界,里面都有一个东西, ...
- C#设计模式之十八状态模式(State Pattern)【行为型】
一.引言 今天我们开始讲“行为型”设计模式的第六个模式,该模式是[状态模式],英文名称是:State Pattern.无论是现实世界,还是面向对象的OO世界,里面都有一个东西,那就是对象.有对象当然就 ...
- 设计模式(java)--状态模式
状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...
随机推荐
- Java中的集合排序
1. 定义排序 class ComparatorDefault implements Comparator { public int compare(Object arg0, Object arg1) ...
- Ubuntu 部署Postgresql
安装组件 客户端安装 sudo apt-get install postgresql-client 服务器安装 sudo apt-get install postgresql postgresql-c ...
- 在MySQL中出现Unknown column 'abc' in 'field list'怎么解决?
update TABLE1 set NAME = '?' where ID ='?' 参数字段需要添引号.
- python-异常处理
一.异常 异常是什么? 就是影响程序正常执行的事件,异常在程序执行的过程中发生,脚本发生异常时,我们需要捕获它,否则程序就会终止. 异常处理: 1.捕获异常:try:...except ..... w ...
- Es6 箭头函数
1.单参数function cheng(a=3){ return a*a;}let cheng= (a=3)=>a*a;console.log(cheng(9));2.多参数functio ...
- flex 布局笔记
1,今天遇到一个问题,就是当元素布局设置为了flex后,里面的内容只有文字,但是对text-align 属性设置无效,仔细想了下,是因为把display 设置为了flex后,flex将里面的文字也认为 ...
- 最好用的JQuery插件集合以及组合拳
[Tab页签] Jquery-tab [Table] mmGrid
- 为什么目前没有"成熟"的cookie插件?
一.序言 最近真是挺忙的啊,导致也挺久没有时间来看看园中各位大神的文章,只能感慨业务真尼玛的多,所以在此写下一篇文章来大话最近工作和学习上面的一点点收获体会,希望大家能够有所收获,这篇文章虽然说是一篇 ...
- manachor
在原字符串每个字符间各插入一个未曾出现的字符,在字符串头插入另一个未出现的字符防止越界,求出的p[i]-1既为以i为中心的最长回文串的长度 void manacher(){ ,id; ;i<=n ...
- Learning to rank 介绍
PS:文章主要转载自CSDN大神hguisu的文章"机器学习排序": http://blog.csdn.net/hguisu/article/details/79 ...