状态模式(State)的定义

定义对象间的一种一对多的依赖关系,当一个对象的状态(对象内部的属性,可以理解成是对象的某个字段或者方法)发生改变时,所有依赖于它的对象都得到通知并被自动更新。允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类

状态模式(State)适用性

1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。

2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

这个状态通常用一个或多个枚举常量表示。

通常,有多个操作包含这一相同的条件结构。

State模式将每一个条件分支放入一个独立的类中。

这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

状态模式(State)的参与者

1.Context

定义客户感兴趣的接口。

维护一个ConcreteState子类的实例,这个实例定义当前状态。

2.State

定义一个接口以封装与Context的一个特定状态相关的行为。

3.ConcreteStatesubclasses

每一子类实现一个与Context的一个状态相关的行为。

状态模式(State)的UML类图

        

具体代码实现:

定义State

//定义和Context中的状态相对应的行为
public interface State {
//获取天气情况
String getState();
}

定义Context

 //定义当前的状态
public class Context { private State state; public State getState() {
return state;
} public void setState(State state) {
this.state = state;
}
public String stateMessage(){
return state.getState();
}
} 

定义ConcreteStatesubclasses

class Sunshine implements State{

    @Override
public String getState() { return "晴天";
} }
class Rain implements State{ @Override
public String getState() { return "下雨";
} } 

测试一下

public class StateTest {

     public static void main(String args[]){

         Context context=new Context();
context.setState(new Rain()); System.out.println(context.stateMessage()); context.setState(new Sunshine());
System.out.println(context.stateMessage());
}
}

运行结果:

下雨
晴天

接下来我们用Java编程思想中的一个例子来讲解一下状态模式

  我们学习了多态,看起来似乎所有的东西都可以去继承,因为多态是一个如此巧妙的工具。事实上,当我们使用现成的类建立新类时,如果首先考虑使用继承技术,反倒会加重我们的设计负担,使得事情变得复杂起来。

  更好的设计思想是首先选择"组合",尤其是不能十分确定应该使用哪一种方式的时候。组合不会强制我们的程序设计进入继承的层次结构中。而且,组合更加灵活,因为它可以动态选择类型(因此也就选择了行为),想法,继承在编译时就需要知道确定的类型,下面是具体代码体现:

//相当于状态模式中的state
class Actor { public void act(){
}
}
//相当于状态模式中的ConcreteStateSubclassess
class HappyActor extends Actor{
public void act(){
System.out.println("HappyActor");
}
}
class SadActor extends Actor{
public void act(){
System.out.println("SadActor");
}
}
//相当于状态模式中的Context
class Stage{
private Actor actor=new HappyActor();
//改变引用actor的指向的具体类型
public void change(){
actor=new SadActor();
}
//根据状态的不同执行不同的行为
public void performPlay(){
actor.act();
}
} 

测试一下:

public class Transmogrify {

    /**
* @param args
*/
public static void main(String[] args) { Stage stage=new Stage();
stage.performPlay();
stage.change();
stage.performPlay();
} }

运行结果:

HappyActor
SadActor

程序分析:在这里,Stage对象包含一个对Actor的引用,而Actor被初始化为HappyActor对象,这意味着performPlay()会产生某种特殊行为。既然引用在运行时可以和另一个不同的对象重新绑定起来,SadActor对象的引用可以在actor中被替换,然后由performPlay()产生的行为也随之改变,这样一来,我们在运行期间获得了动态灵活性。与此相反的是,我们不能在运行期间决定继承不同的对象,因为它要求在编译期间完全确定下来。

大家是不是觉得状态模式和策略模式不是一样的吗?我们讲一下他们之间的区别和联系:

状态模式和策略模式的区别和联系(取自知乎网友的回答,很精辟):

区别:
状态模式将各个状态所对应的操作分离开来,即对于不同的状态,由不同的子类实现具体操作,不同状态的切换由子类实现,当发现传入参数不是自己这个状态所对应的参数,则自己给Context类切换状态;而策略模式是直接依赖注入到Context类的参数进行选择策略,不存在切换状态的操作联系。
联系:
状态模式和策略模式都是为具有多种可能情形设计的模式,把不同的处理情形抽象为一个相同的接口,符合对扩展开放,对修改封闭的原则。还有就是,策略模式更具有一般性一些,在实践中,可以用策略模式来封装几乎任何类型的规则,只要在分析过程中听到需要在不同实践应用不同的业务规则,就可以考虑使用策略模式处理,在这点上策略模式是包含状态模式的功能的,策略模式是一个重要的设计模式。

Java设计模式系列之状态模式的更多相关文章

  1. 重学 Java 设计模式:实战状态模式「模拟系统营销活动,状态流程审核发布上线场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! @ 目录 一.前言 二.开发环境 三.状态模式介绍 四.案例场景模拟 1 ...

  2. Java设计模式系列-抽象工厂模式

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...

  3. Java设计模式系列-工厂方法模式

    原创文章,转载请标注出处:<Java设计模式系列-工厂方法模式> 一.概述 工厂,就是生产产品的地方. 在Java设计模式中使用工厂的概念,那就是生成对象的地方了. 本来直接就能创建的对象 ...

  4. Java设计模式系列-装饰器模式

    原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...

  5. Java设计模式学习记录-状态模式

    前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使 ...

  6. 《Java设计模式》之状态模式

    状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式. 状态模式同意一个对象在其内部状态改变的时候改变其行为.这个对象看上去就像是改变了它 ...

  7. java设计模式-----22、状态模式

    概念: State模式也叫状态模式,是行为设计模式的一种.State模式允许通过改变对象的内部状态而改变对象的行为,这个对象表现得就好像修改了它的类一样. 根据这个概念,我们举个例子 public c ...

  8. 《JAVA设计模式》之状态模式(State)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述状态(State)模式的: 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为 ...

  9. C#设计模式系列:状态模式(State)

    1.状态模式简介 1.1>.定义 状态模式的核心思想是允许一个对象在它的内部状态改变时改变它的行为,即不同的状态对应不同的行为. 状态模式的针对性很强,当有状态变化的时候可以选择状态模式. 1. ...

随机推荐

  1. 《Linux/Unix系统编程手册》读书笔记1

    <Linux/Unix系统编程手册>读书笔记 目录 最近这一个月在看<Linux/Unix系统编程手册>,在学习关于Linux的系统编程.之前学习Linux的时候就打算写关于L ...

  2. UserAccountInfo时间倒计时

    界面如下: 代码如下: using System;using System.Collections.Generic;using System.ComponentModel;using System.D ...

  3. 三个Timer

    System.Windows.Forms.Timer System.Timers.Timer System.Threading.Timer 关于这三者的区别,可以参见msdn     https:// ...

  4. Windows Tomcat 安装

    JDK的安装可以参考 http://www.cnblogs.com/emanlee/p/3702535.html ,然后安装apache-tomcat step1:http://tomcat.apac ...

  5. new int[]和new int()的区别

    1. new int[] 是创建一个int型数组,数组大小是在[]中指定,例如:int * p = new int[10]; //p执行一个长度为10的int数组.2. new int()是创建一个i ...

  6. oracle索引,索引的建立、修改、删除

    索引,索引的建立.修改.删除 2007-10-05 13:29 来源: 作者: 网友评论 0 条 浏览次数 2986 索引索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度和 ...

  7. Oracle默认的用户名和密码

    你是说默认的用户名和密码么scott 密码是 tigersys 密码是 change_on_installsystem 密码是 managersysman 密码是 oem_temp 其中直接管理模式可 ...

  8. WEB-INF目录与META-INF目录的作用

    /WEB-INF/web.xml Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则. /WEB-INF/classes/包含了站点所有用的 class 文件,包括 ser ...

  9. BZOJ 3527 力

    fft推下公式.注意两点: (1)数组从0开始以避免出错. (2)i*i爆long long #include<iostream> #include<cstdio> #incl ...

  10. HDU 5313 Bipartite Graph (二分图着色,dp)

    题意: Soda有一个n个点m条边的二分图, 他想要通过加边使得这张图变成一个边数最多的完全二分图. 于是他想要知道他最多能够新加多少条边. 注意重边是不允许的. 思路: 先将二分图着色,将每个连通分 ...