一,总体概要

1,笔者浅谈

状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式。

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

 var TrafficLight = function () {
var count = 0;
var currentState = new Red(this); this.change = function (state) {
// limits number of changes
if (count++ >= 10) return;
currentState = state;
currentState.go();
}; this.start = function () {
currentState.go();
};
}
var Red = function (light) {
this.light = light; this.go = function () {
log.add("Red --> for 1 minute");
light.change(new Green(light));
}
};
var Yellow = function (light) {
this.light = light; this.go = function () {
log.add("Yellow --> for 10 seconds");
light.change(new Red(light));
}
};
var Green = function (light) {
this.light = light; this.go = function () {
log.add("Green --> for 1 minute");
light.change(new Yellow(light));
}
};
var log = (function () {
var log = ""; return {
add: function (msg) { log += msg + "\n"; },
show: function () { alert(log); log = ""; }
}
})(); function run() {
var light = new TrafficLight();
light.start(); log.show();
}

在示例代码中分为三种状态:红色,黄色,绿色

我们的例子是一个交通灯(即信号灯对象)有3种不同的状态:红色,黄色和绿色,各有自己的一套规则。规则是这样的:交通灯是红色的。延迟红状态变为绿色状态后。然后,一段时间后,绿色的状态更改为黄色的状态。

一个非常短暂的延迟黄色状态变为红色后,等等。

需要注意的是,它是对象状态决定下一个状态过渡的重要。这也是对象状态变化,交通灯的当前状态------没有交通灯本身。

出于演示的目的,一个内置的计数器记录状态发生变化的数量,否则程序会运行下去。日志功能是一个帮助它收集并显示结果。

二,源码案例参考

采用让状态对象来维护和转换状态的调用顺序

1)调用上下文的方法来处理业务请求。

2)获取State对象。

3)委托让相应的状态对象去处理。

4)调用方法得到下一个状态方法。

5)设置下一个状态方法。

6)再到5),直到结束。

三,案例引入

再次强调一下状态模式的意图

Context: 环境,也称上下文,通常用来定义客户感兴趣的接口,同时维护一个具体处理当前状态的实例对象。

State:状态接口,用来封装与上下文的一个特定状态所对应的行为。

ConcreteState: 具体实现状态处理的类,每个类实现一个跟上下文相关的状态的具体处理。

例子场景:

模拟工作流中的请假流程,流程是这样的:

当某人提出请假申请,先由项目经理审批,

如果项目经理不同意,审批就直接结束;

如果项目经理同意了,再看请假的天数是否超过3天,项目经理的审批权限只有3天以内,

如果请假天数在3天以内,那么审批也直接结束,

否则就提交给部门经理,部门经理审核过后,无论是否同意,审批都直接结束。

 (function () {
// 模拟工作流 // 定义请假单的业务数据模型
function LeaveRequestModel() {
// 请假人
this.user = '';
// 请假开始时间
this.beginDate = '';
// 请假天数
this.leaveDays = '';
// 审核结果
this.result = '';
} /*
请假流程,需项目经理和部门经理审批
*/ function LeaveRequestContext2() {
this.state = null;
// 包含流程处理需要的业务数据对象
this.businessVO = null;
this.doWork = function () {
if (typeof this.state == 'function') {
this.state = this.state(this);
this.doWork();
}
};
} function projectManagerState(request) {
var leaveRequestModel = request.businessVO; console.log('项目经理审核中,请稍候。。');
console.log(leaveRequestModel.user + '申请从'
+ leaveRequestModel.beginDate + '开始请假'
+ leaveRequestModel.leaveDays + '天,请项目经理审核(1为同意,2为不同意)'); var answer = window.prompt('1为同意,2为不同意');
var result = answer == 1 ? '同意' : '不同意';
leaveRequestModel.result = '项目经理审核结果:' + result; var state;
if (answer == 1) {
if (leaveRequestModel.leaveDays > 3) {
state = depManagerState;
} else {
state = auditOverState;
}
} else {
state = auditOverState;
} return state;
} function depManagerState(request) {
var leaveRequestModel = request.businessVO; console.log('部门经理审核中,请稍候。。');
console.log(leaveRequestModel.user + '申请从'
+ leaveRequestModel.beginDate + '开始请假'
+ leaveRequestModel.leaveDays + '天,请项目经理审核(1为同意,2为不同意)'); var answer = window.prompt('1为同意,2为不同意');
var result = answer == 1 ? '同意' : '不同意';
leaveRequestModel.result = '部门经理审核结果:' + result; return auditOverState;
} function auditOverState(request) {
var leaveRequestModel = request.businessVO;
// do sth
console.log(leaveRequestModel.user + ',你的请假申请已经审核结束,结果是:' + leaveRequestModel.result);
} var lrm = new LeaveRequestModel();
lrm.user = '小林';
lrm.beginDate = '2014-4-2';
lrm.leaveDays = 5; var request = new LeaveRequestContext2();
request.businessVO = lrm;
request.state = projectManagerState; request.doWork(); }());

四,总结一下

认识状态模式

  使用场景

  State模式在实际使用中比较多,适合"状态的切换"。因为我们经常会使用If else if else 进行状态切换,如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了。

  不只是根据状态,也有根据属性。如果某个对象的属性不同,对象的行为就不一样,这点在Database系统中出现频率比较高,我们经常会在一个数据表的尾部,加上property属性含义的字段,

  用以标识记录中一些特殊性质的记录,这种属性的改变(切换)又是随时可能发生的,就有可能要使用State。

  状态和行为

  所谓对象的状态,通常指的就是对象实例的属性的值;而行为指的就是对象的功能,再具体点说,行为大多可以对应到方法上。

  状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对应的不同功能。也就是说,状态和行为是相关联的,它们的关系可以描述为:状态决定行为

  由于状态是在运行期被改变的,因此行为也会在运行期根据状态的改变而改变。

  行为的平行性

  注意平行线而不是平等性。所谓平行性指的是各个状态的行为所处的层次是一样的,相互独立的、没有关联的,是根据不同的状态来决定到底走平行线的哪一条。

  行为是不同的,当然对应的实现也是不同的,相互之间是不可替换的。

  环境和状态处理对象

  在状态模式中,环境(Context)是持有状态的对象,但是环境(Context)自身并不处理跟状态相关的行为,而是把处理状态的功能委托给了状态对应的状态处理类来处理。

  在具体的状态处理类中经常需要获取环境(Context)自身的数据,甚至在必要的时候会回调环境(Context)的方法,因此,通常将环境(Context)自身当作一个参数传递给具体的状态处理类。

  客户端一般只和环境(Context)交互。客户端可以用状态对象来配置一个环境(Context),一旦配置完毕,就不再需要和状态对象打交道了。客户端通常不负责运行期间状态的维护,也不负责决定后续到底使用哪一个具体的状态处理对象。

  

  哈哈哈,本篇结束,未完待续,希望和大家多多交流够沟通,共同进步。。。。。。呼呼呼……(*^__^*)            

大熊君说说JS与设计模式之------状态模式State的更多相关文章

  1. 大熊君说说JS与设计模式之------代理模式Proxy

    一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...

  2. 大熊君说说JS与设计模式之------命令模式Command

    一,总体概要 1,笔者浅谈 日常生活中,我们在看电视的时候,通过遥控器选择我们喜欢的频道时,此时我们就是客户端的角色,遥控器的按钮相当于客户请求,而具体执行的对象就是命令对象, 命令模式把一个请求或者 ...

  3. 大熊君说说JS与设计模式之------策略模式Strategy

    一,总体概要 1,笔者浅谈 策略模式,又叫算法簇模式,就是定义了不同的算法,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 策略模式和工厂模式有一定的类似,策略模式相对简单容易理解,并 ...

  4. 【转】设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  5. 设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

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

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

  7. 北风设计模式课程---状态模式State(对象行为型)

    北风设计模式课程---状态模式State(对象行为型) 一.总结 一句话总结: 状态模式 具体状态的行为在具体的状态类中就解决,不用交给外部做判断.实质是将多条件判断弄成了多个类,在不同的类中做判断 ...

  8. 设计模式2——状态模式State

    参考链接: 设计模式之状态模式:https://www.cnblogs.com/haoerlv/p/7777789.html 设计模式系列之状态模式:https://www.jianshu.com/p ...

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

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

随机推荐

  1. XidianOJ 1120 Gold of Orz Pandas

    题目描述 Orz Panda is addicted to one RPG game. To make his character stronger, he have to fulfil tasks ...

  2. MySQL_杭州北仓 12.3-12.7需求活动期间累计下单达到3天及以上的客户_20161212

    #C025_02杭州北仓 12.3-12.7需求活动期间累计下单达到3天及以上的客户明细 SELECT d.*,CASE WHEN 下单天次>=3 THEN "下单超过3天" ...

  3. vc++ basic chapt1

    ______API 和SDK _像c程序可以调用各种函数库一样, windows操作系统提供应用程序编程的接口application programming interface简称API函数. 所以主 ...

  4. "Asp.Net Web Api MediaTypeFormatter Error for x-www-formurlencoded data" 解决方法

    遇到标题中所说的问题原因是使用 jQuery AJAX 以 POST 方式调用 Asp.Net Web API .解决办法请看以下代码中有注释的部分. public static class WebA ...

  5. codeforces731C Socks

    C. Socks time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  6. 关于“ora-01483:DATE或NUMBER赋值变量的长度无效”的问题

    关于“ora-01483:DATE或NUMBER赋值变量的长度无效”的问题 出现这样的问题,一般都是驱动不匹配的原因导致的

  7. asp.net GridView控件的列属性

    BoundField 默认的数据绑定类型,通常用于显示普通文本 CheckBoxField 显示布尔类型的数据.绑定数据为TRUE时,复选框数据绑定列为选中状态:绑定数据为FALSE时,则显示未选中状 ...

  8. 使用C# WinForm窗体制作经理评分项目 ——S2 2.2

    在窗口加载时初始化三个员工对象 用数组存放 这是员工类的大致字段和属性. 在FrmMain中给对象数组附初值 以上 FrmMain中用一个ListView控件展示员工信息,通过以上代码将对象数组中的内 ...

  9. getpid 与 gettid 与 pthread_self

    获取进程的PID(process ID) #include <unistd.h> pid_t getpid(void); 获取线程的TID(thread ID) 1)gettid或者类似g ...

  10. 在Linux终端命令行下播放音乐的命令(Ubuntu)

    现在的 Linux 桌面已经发展的很好了,在桌面下播放音乐操作起来也很简单.那么我们还记得在桌面不是那么好的时候我们是怎么播放音乐的么?哎,我是想不起来了,实在是太难了. 不过现在我们可以先安装一个小 ...