概念:

  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. 回头探索JDBC及PreparedStatement防SQL注入原理

    概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...

  2. 【kuangbin专题】计算几何_凸包

    1.poj1113 Wall 题目:http://poj.org/problem?id=1113 题意:用一条线把若干个点包起来,并且线距离任何一个点的距离都不小于r.求这条线的最小距离是多少? 分析 ...

  3. python实用库:PrettyTable 学习

    python实用库:PrettyTable 学习 PrettyTable说明 PrettyTable 是python中的一个第三方库,可用来生成美观的ASCII格式的表格,十分实用. 以下为官方介绍: ...

  4. 原生JS实现AJAX、JSONP及DOM加载完成事件,并提供对应方法

    JS原生AJAX ajax:一种请求数据的方式,不需要刷新整个页面: ajax的技术核心是 XMLHttpRequest 对象: ajax 请求过程:创建 XMLHttpRequest 对象.连接服务 ...

  5. Vue2.5开发去哪儿网App 第四章笔记 下

    1.解决非父子组件之间的传值问题 非父子组件传值(Bus/总线/发布订阅模式/观察者模式) 给 Vue类上挂在一个属性,然后创建vue实例时,实例就拥有了这个属性 Vue.prototype.bus ...

  6. 09-02 java 多态

    多态的前提.多态的特点 /* 多态:同一个对象(事物),在不同时刻体现出来的不同状态. 举例: 猫是猫,猫是动物. 水(液体,固体,气态). 多态的前提: A:要有继承关系. B:要有方法重写. 其实 ...

  7. mac操作记录

    1.mac'主目录地址' 类似我的电脑 点桌面空白处按shift+command+C, 双击Macintosh HD图标后就能看见system文件夹 2.做excel表格,下载Microsoft Of ...

  8. 剑指offer十一之二进制中1的个数

    一.题目 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 二.思路 方法一: 用1(1自身左移运算,其实后来就不是1了)和n的每位进行位与,来判断1的个数 方法二: 把一个整数减去1 ...

  9. PHP的语言构造器

    isset和empty看起来像是函数,我们也经常把它当作函数一样使用,但是实际上,它们是语言构造器. php中的语言构造器就相当于C中的预定义宏的意思,它属于php语言内部定义的关键词,不可以被修改, ...

  10. Redis学习系列五Set(集合)

    一.简介 Redis中的Set(集合)相当于C#中的HashSet,它内部的键值对时无序的.唯一的.用过Dictionary的都知道,Dictionary都知道,里面的每个键值对肯定是唯一的,因为键不 ...