概念:

  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. TCPDUMP学习笔记。

    1.启动 普通情况下,直接启动tcpdump将监视第一个网络界面上所有流过的数据包,注意这里使用超级用户.当用户上网得时候,就会将监视得数据打印出来. 我没使用root用户,结果输入tcpdump命令 ...

  2. python并发编程之进程池,线程池concurrent.futures

    进程池与线程池 在刚开始学多进程或多线程时,我们迫不及待地基于多进程或多线程实现并发的套接字通信,然而这种实现方式的致命缺陷是:服务的开启的进程数或线程数都会随着并发的客户端数目地增多而增多, 这会对 ...

  3. [Spring]@Autowired,@Required,@Qualifier注解

    @Required注解 @Required注解用于setter方法,表明这个属性是必要的,不可少的,必须注入值 假设有个测试类,里面有name和password两个属性 我给两个属性的setter方法 ...

  4. POJ 2487

    #include<iostream> #include<stdio.h> using namespace std; int compare(void const * i,voi ...

  5. Java语言基础(方法与数组)_DAY05

    1:函数(掌握)   (1)定义在类中,有特定功能的一段小程序,可以独立运行.    (2)函数的格式:       修饰符 返回值类型 函数名(形参类型 形式参数1,形参类型 形式参数2...)   ...

  6. 监督学习——AdaBoost元算法提高分类性能

    基于数据的多重抽样的分类器 可以将不通的分类器组合起来,这种组合结果被称为集成方法(ensemble method)或者元算法(meta-algorithom) bagging : 基于数据随机抽样的 ...

  7. 【从0到1学Web前端】CSS定位问题一(盒模型,浮动,BFC) 分类: HTML+CSS 2015-05-27 22:24 813人阅读 评论(1) 收藏

    引子: 在谈到css定位问题的时候先来看一个小问题: 已知宽度(假如:100px)div框,水平居中,左右两百年的分别使用div框填充.且左右div自适应. 效果如下图: 这个问题的难点主要是浏览器宽 ...

  8. Mysql大数据表优化处理

    原文链接: https://segmentfault.com/a/1190000006158186 当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表 ...

  9. Android四大组件之一 -- Service详解

    相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的Android程序员如果连Service都没听说过的话,那确实也太逊了.Service作为Android四大组件之一,在每一个应用程序 ...

  10. [转]让程序不触发 Vista/Win7下应用程序兼容性助手弹出 .

    原文地址 http://blog.csdn.net/maxuhuiabc/article/details/6081874 在Vista/Win7下 运行一个 exe 应用程序后,系统经常弹出 兼容性助 ...