状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来是改变了其类。

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

既然状态者模式是对已有对象的状态进行抽象,则自然就有抽象状态者类和具体状态者类,而原来已有对象需要保存抽象状态者类的引用,通过调用抽象状态者的行为来改变已有对象的行为。经过上面的分析,状态者模式的结构图也就很容易理解了,具体结构图如下图示。

从上图可知,状态者模式涉及以下三个角色:

  • Account类:维护一个State类的一个实例,该实例标识着当前对象的状态。
  • State类:抽象状态类,定义了一个具体状态类需要实现的行为约定。
  • SilveStater、GoldState和RedState类:具体状态类,实现抽象状态类的每个行为。

C#状态模式:

namespace 状态模式
{
class Program
{
static void Main(string[] args)
{
//紧急项目
Work emergencyProjects = new Work();
emergencyProjects.Hour = ;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = ;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = ;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = ;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = ;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = ; //emergencyProjects.WorkFinished = true;
emergencyProjects.TaskFinished = false; emergencyProjects.WriteProgram();
emergencyProjects.Hour = ;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = ;
emergencyProjects.WriteProgram(); Console.Read();
}
} //抽象状态
public abstract class State
{
public abstract void WriteProgram(Work w);
} //上午工作状态
public class ForenoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < )
{
Console.WriteLine("当前时间:{0}点 上午工作,精神百倍", w.Hour);
}
else
{
w.SetState(new NoonState());
w.WriteProgram();
}
}
} //中午工作状态
public class NoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < )
{
Console.WriteLine("当前时间:{0}点 饿了,午饭;犯困,午休。", w.Hour);
}
else
{
w.SetState(new AfternoonState());
w.WriteProgram();
}
}
} //下午工作状态
public class AfternoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < )
{
Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力", w.Hour);
}
else
{
w.SetState(new EveningState());
w.WriteProgram();
}
}
} //晚间工作状态
public class EveningState : State
{
public override void WriteProgram(Work w)
{
if (w.TaskFinished)
{
w.SetState(new RestState());
w.WriteProgram();
}
else
{
if (w.Hour < )
{
Console.WriteLine("当前时间:{0}点 加班哦,疲累之极", w.Hour);
}
else
{
w.SetState(new SleepingState());
w.WriteProgram();
}
}
}
} //睡眠状态
public class SleepingState : State
{
public override void WriteProgram(Work w)
{
Console.WriteLine("当前时间:{0}点 不行了,睡着了。", w.Hour);
}
} //下班休息状态
public class RestState : State
{
public override void WriteProgram(Work w)
{
Console.WriteLine("当前时间:{0}点 下班回家了", w.Hour);
}
} //工作
public class Work
{
private State current;
public Work()
{
current = new ForenoonState();
} private double hour;
public double Hour
{
get { return hour; }
set { hour = value; }
} private bool finish = false;
public bool TaskFinished
{
get { return finish; }
set { finish = value; }
} public void SetState(State s)
{
current = s;
} public void WriteProgram()
{
current.WriteProgram(this);
}
}
}

状态者模式的应用场景

在以下情况下可以考虑使用状态者模式。

  • 当一个对象状态转换的条件表达式过于复杂时可以使用状态者模式。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。
  • 当一个对象行为取决于它的状态,并且它需要在运行时刻根据状态改变它的行为时,就可以考虑使用状态者模式。

javascript版本的状态机:

var Light = function(){
this.currState = FSM.off; //设置当前状态
this.button = null;
}; Light.prototype.init = function(){
var button = document.createElement('button'),
self = this; button.innerHTML = '已关灯';
this.button = document.body.appendChild(button); this.button.onclick = function(){
self.currState.buttonWasPressed.call(self); //把请求委托给FSM状态机
}
}; var FSM = {
off:{
buttonWasPressed:function(){
console.log('关灯');
this.button.innerHTML = '下一次按我是开灯';
this.currState = FSM.on;
}
},
on:{
buttonWasPressed:function(){
console.log('开灯');
this.button.innerHTML = '下一次按我是关灯';
this.currState = FSM.off;
}
}
}; var light = new Light();
light.init();

实际项目中的其他状态机:

var FSM = {
walk:{
attack:function(){
console.log('攻击');
},
defense:function(){
console.log('防御');
},
jump:function(){
console.log('跳跃');
}
}, attack:{
walk:function(){
console.log('攻击的时候不能行走');
},
defense:function(){
console.log('攻击的时候不能防御');
},
jump:function(){
console.log('攻击的时候不能跳跃');
}
}
};

状态模式的电灯程序:

var  Light = function(){
this.currState = FSM.off; //设置当前状态
}; Light.prototype.init = function(){
self = this; this.button.onclick = function(){
self.currState.buttonWasPressed.call(self); //把请求委托给FSM状态机
}
}; var FSM = {
off:{
buttonWasPressed:function(){
console.log('弱光');
this.currState = FSM.weak;
}
},
weak:{
buttonWasPressed:function(){
console.log('强光');
this.currState = FSM.strong;
}
},
strong:{
buttonWasPressed:function(){
console.log('关灯');
this.currState = FSM.off;
}
}
}; var light = new Light();
light.init();

状态模式-水的三态变化

用js模拟物理现象,实现水的三态变化,初中物理课我们都学过,物质具有三态变化,气态 -> 液态 -> 固态 或者 固态 -> 液态 -> 气态,但是不可以气态 -> 固态,或者固态 -> 气态,是需要经过液态过度的,否则就违反了自然规律。所以这种状态的变化非常适合用状态模式来实现。代码如下:

var Water = function(){
this.currState = FSM.gas; //设置当前状态
this.h3 = null;
}; Water.prototype.init = function(){
var button1 = document.createElement('button'),
button2 = document.createElement('button'),
button3 = document.createElement('button'),
h3 = document.createElement('h3'),
self = this; button1.innerHTML = '100度以上';
button1.onclick = function(){
self.currState.gas.call(self);
} button2.innerHTML = '0-100度';
button2.onclick = function(){
self.currState.liquid.call(self);
} button3.innerHTML = '0度以下';
button3.onclick = function(){
self.currState.solid.call(self);
} document.body.appendChild(button1);
document.body.appendChild(button2);
document.body.appendChild(button3);
this.h3 = document.body.appendChild(h3);
}; var FSM = {
gas:{ //气态
liquid:function(){
console.log('液态');
this.h3.innerHTML = '液态';
this.currState = FSM.liquid;
},
solid:function(){
console.log('气态不能变化为固态');
alert('气态不能变化为固态');
}
},
liquid:{ //液态
solid:function(){
console.log('固态');
this.h3.innerHTML = '固态';
this.currState = FSM.solid;
},
gas:function(){
console.log('气态');
this.h3.innerHTML = '气态';
this.currState = FSM.gas;
}
},
solid:{ //固态
gas:function(){
console.log('固态不能变化为气态');
alert('固态不能变化为气态');
},
liquid:function(){
console.log('液态');
this.h3.innerHTML = '液态';
this.currState = FSM.liquid;
}
}
};
var water = new Water();
water.init();

最新文章

  1. C#Linq技术中SelectMany(...)的内部实现推测
  2. IOS开发基础知识--碎片43
  3. 配置webdriver环境
  4. [Python] Remote debugging by Pycharm
  5. javascript arguments
  6. iOS开发——UI高级OC篇&amp;自定义控件之调整按钮中子控件(图片和文字)的位置
  7. java中的synchronized关键字
  8. Maven 打胖jar
  9. redis怎么动态添加内存,动态配置,无需重启。
  10. Alamofire网络库基础教程
  11. CodeForces 617C Watering Flowers
  12. 为实施了IFD的Dynamics 365更换自签名的SSL证书以符合Chrome的要求
  13. vxWorks驱动架构
  14. .NET CORE 使用Dapper连接MSSQL,MYSQL
  15. Django启动报错笔记
  16. keras框架 反复调用model 模型 出错
  17. 【AaronYang风格】第一篇 CodeFirst 初恋
  18. 【WPF】修改数据层ViewModel后,UI界面未同步更新
  19. php安装redis扩展全
  20. mysql 怎么给一个表一次增加多个字段, mysql 添加 多个 字段

热门文章

  1. MySQL第一天
  2. MapReduceTopK TreeMap
  3. vim常规操作
  4. 爬虫五 Beautifulsoup模块详细
  5. 剑指offer 面试19题
  6. 标准C语言的输入输出流(i/o)方法详解
  7. $用python实现快速排序算法
  8. Linux Shell编程 循环语法
  9. 定制AIX操作系统的shell环境
  10. 【Tech】单点登录系统CAS客户端demo