概念:

  State模式也叫状态模式,是行为设计模式的一种。State模式允许通过改变对象的内部状态而改变对象的行为,这个对象表现得就好像修改了它的类一样。

  根据这个概念,我们举个例子

 public class Behavior {
private int time; public int getTime() {
return time;
} public void setTime(int time) {
this.time = time;
} public void eat(){
if(time == 7){
System.out.println("吃早饭");
}else if(time == 12){
System.out.println("吃午饭");
}else if(time == 18){
System.out.println("吃晚饭");
}else{
System.out.println("还不到吃饭时间");
}
}
}
 public class MainClass {
public static void main(String[] args) {
Behavior behavior = new Behavior();
behavior.setTime(7);
behavior.eat(); behavior.setTime(12);
behavior.eat(); behavior.setTime(18);
behavior.eat(); behavior.setTime(20);
behavior.eat();
}
}

  结果:

  可以看到,根据time属性的不同,对象的行为也发生了改变,但是这样的方式很不好,所有的事情都放到了eat()方法中,导致eat()方法过于复杂

  下面就看一看状态模式

  状态模式的应用场景

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

  简单来说:

  1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  2.一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。

  状态模式的结构

  

  状态模式的角色和职责

  1、Context:用户对象:拥有一个State类型的成员,以标识对象的当前状态(Behavior)

  2、State:接口或基类封装与Context的特定状态相关的行为;

  3、ConcreteState:接口实现类或子类实现了一个与Context某个状态相关的行为。

  按照状态模式,我们来改造一下,刚才的例子,吃早中晚饭,不是吃饭时间,都是状态,所以我们把状态单独封装出来。

  首先,新建一个State

 public abstract class State {
public abstract void eat();
}

  接着新建ConcreteState

 /*
* 早餐
*/
public class BreakfastState extends State { @Override
public void eat() {
System.out.println("吃早餐");
} }
 /*
* 午餐
*/
public class LunchState extends State { @Override
public void eat() {
System.out.println("吃午餐");
} }
 /*
* 晚餐
*/
public class DinnerState extends State { @Override
public void eat() {
System.out.println("吃晚餐");
} }
 /*
* 不是吃饭时间
*/
public class NoFoodState extends State { @Override
public void eat() {
System.out.println("不是吃饭时间");
} }

  再修改一下behavior

 public class Behavior {
private int time;
State state = null; public int getTime() {
return time;
} public void setTime(int time) {
this.time = time;
} public void eat(){
if(time == 7){
state = new BreakfastState();
state.eat();
}else if(time == 12){
state = new LunchState();
state.eat();
}else if(time == 18){
state = new DinnerState();
state.eat();
}else{
state = new NoFoodState();
state.eat();
}
}
}

  这样,和刚才的结果一样,但是这样子,判断逻辑还是在对象中,我们继续修改,将逻辑写到ConcreteState

  因为,我们要知道time,所以需要向state中传入参数,所以我们将Behavior传进去

 public abstract class State {
public abstract void eat(Behavior behavior);
}

  然后,修改Behavior

 public class Behavior {
private int time;
State state = null; public Behavior() {
state = new BreakfastState();
} public int getTime() {
return time;
} public void setTime(int time) {
this.time = time;
} public State getState() {
return state;
} public void setState(State state) {
this.state = state;
} public void eat(){
//逻辑取出,所以这里只剩调用方法
state.eat(this);
//当所有方法都完成后,回到最初始状态
state = new BreakfastState();
}
}

  接着,再继续修改每一个ConcreteState

 /*
* 早餐
*/
public class BreakfastState extends State { @Override
public void eat(Behavior behavior) {
if(behavior.getTime() == 7){
System.out.println("吃早餐");
}else{
//如果不符合条件,重置state为下一个状态
behavior.setState(new LunchState());
behavior.eat();
}
}
}
 /*
* 午餐
*/
public class LunchState extends State { @Override
public void eat(Behavior behavior) {
if(behavior.getTime() == 12){
System.out.println("吃午餐");
}else{
behavior.setState(new DinnerState());
behavior.eat();
}
} }
 /*
* 晚餐
*/
public class DinnerState extends State { @Override
public void eat(Behavior behavior) {
if(behavior.getTime() == 18){
System.out.println("吃晚餐");
}else{
behavior.setState(new NoFoodState());
behavior.eat();
}
} }
 /*
* 不是吃饭时间
*/
public class NoFoodState extends State { @Override
public void eat(Behavior behavior) {
System.out.println("不是吃饭时间");
} }

  这样,结果和之前是一样的

  状态模式的优点与缺点

  优点: 1、封装了转换规则。

      2、枚举可能的状态,在枚举状态之前需要确定状态种类。

      3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。

      4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

      5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

  缺点: 1、状态模式的使用必然会增加系统类和对象的个数。

      2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

        3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

 注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。

java设计模式-----22、状态模式的更多相关文章

  1. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  2. JAVA设计模式--State(状态模式)

    状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...

  3. JAVA设计模式:状态模式

    声明:转载请说明来源:http://www.cnblogs.com/pony1223/p/7518226.html 一.引出状态模式 假设我们现在有一个糖果机项目,那么我们知道正常一般糖果机提供给用户 ...

  4. Java设计模式之状态模式详解

    (本文由言念小文原创,转载请注明出处) 在实际工作中经常遇到某个对象,处于不同的状态有不同行为逻辑.且状态之间可以相互迁移的业务场景,特别是在开发通信协议栈类软件中尤为多见.<设计模式之禅> ...

  5. java设计模式之状态模式

    状态模式 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类. 状态模式UML图 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关 ...

  6. 曾侯乙编钟引发的遐想之Java设计模式:状态模式

    目录 示例 简单例子 改进代码 状态模式 定义 意图 主要解决问题 何时使用 优缺点 曾侯乙编钟 状态模式-命令模式-策略模式 示例 一个类对外提供了多个行为,同时该类对象有多种状态,不同状态下对外的 ...

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

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

  8. 折腾Java设计模式之备忘录模式

    原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...

  9. 折腾Java设计模式之访问者模式

    博客原文地址:折腾Java设计模式之访问者模式 访问者模式 Represent an operation to be performed on the elements of an object st ...

  10. 折腾Java设计模式之命令模式

    博客原文地址 折腾Java设计模式之命令模式 命令模式 wiki上的描述 Encapsulate a request as an object, thereby allowing for the pa ...

随机推荐

  1. 【BZOJ2882】 工艺(SAM)

    传送门 BZOJCH 洛谷 Solution 这个东西要求的不就是最小表示法吗? 把原串复制一遍然后都加到后缀自动机里面去. 用个map跑一下,这样子可以保证每一次选的是最小字典序的. 然后跑\(n\ ...

  2. 20164317 《网络对抗技术》Exp6 信息搜集与漏洞扫描

    Exp6 信息搜集与漏洞扫描 一.原理与实践说明 (1)实践原理 信息搜集:渗透测试中首先要做的重要事项之一,搜集关于目标机器的一切信息 间接收集 DNS记录扫描和枚举 CorpWatch:auxil ...

  3. 关于ajax访问webservice查询数据量稍微大一点,就会返回error500的解决方案

    只需要在web.config的configeration节点中增加如下子节点即可: <system.web.extensions>       <scripting>      ...

  4. Distinct Substrings(spoj694)(sam(后缀自动机)||sa(后缀数组))

    Given a string, we need to find the total number of its distinct substrings. Input \(T-\) number of ...

  5. 网页关闭(解决window.close在火狐下不兼容问题)

    熟悉前端的都知道,火狐默认状态非window.open的页面window.close是无效的 网上有很多人说,在火狐的地址栏输入:about:config然后找到dom.allow_scripts_t ...

  6. JS简单表单验证

    这里我是写了一个简单的注册表单验证功能,亲测有效,一起来看看吧! 首先我的HTML代码是这样的: class大家可以忽略一下,这里我项目使用的是bootstrap的样式. 输入用户名和密码用的是正则表 ...

  7. Git - 回滚与撤销

    必要的概念 当前编辑界面:工作区(workspace) "git add"命令:将改动加入到缓存区(Index) "git commit"命令:提交代码到本地库 ...

  8. 上下文相关的GMM-HMM声学模型

    一.上下文对音素发音的语谱轨迹的影响 受到上下文的影响,同一个音素的发音语谱轨迹不同 为提高识别准确率,对音素建模时应将这种上下文影响考虑在内 二.基于上下文相关的音素建模 注意,非单音素建模中,每个 ...

  9. Django自带的后台管理样式找不到的问题。

    今天发现自己用uwsgi,nginx部署完服务器后,又想用自带的Django服务器进行后台管理调试,发现Django后代管理页面样式找不到.又查看了路径发现是正确的.网上看了很多方法.最后才发现自己把 ...

  10. ASP.NET WebAPI Bearer Authorization

    使用VS2015新建一个WebApi项目. 关键的配置在Startup.Auth.cs里 public partial class Startup { public static OAuthAutho ...