23种设计模式(22)java状态模式

一、概述

当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。状态模式是一种对象行为型模式。

二、适用场景

用于解决系统中复杂对象的多种状态转换以及不同状态下行为的封装问题。简单说就是处理对象的多种状态及其相互转换。

三、UML类图

四、参与者

1)、AbstractState(抽象状态类):

在抽象状态类中定义申明了不同状态下的行为抽象方法,而由子类(不同的状态子类)中实现不同的行为操作。

2)、ConcreteState(实现具体状态下行为的状态子类):

抽象状态类的子类,每一个子类实现一个与环境类(Context)的一个状态相关的行为,每一个具体的状态类对应环境的一种具体状态,不同的具体状态其行为有所不同。

3)、Context(拥有状态对象的环境类):

拥有状态属性,因环境的多样性,它可拥有不同的状态,且在不同状态下行为也不一样。在环境类中维护一个抽象的状态实例,这个实例定义当前环境的状态(setState()方法),而将具体的状态行为分离出来由不同的状态子类去完成。

五、用例学习

1、抽象状态类:State.java

/**
* JAVA设计模式之 状态模式
* 抽象状态类
* @author lvzb.software@qq.com
*
*/
public abstract class State {
  /**
  * 状态行为抽象方法,由具体的状态子类去实现不同的行为逻辑
  */
  public abstract void Behavior(); 

}

2、具体状态子类A:ConcreteStateA.java

/**
* 具体的状态子类A
* @author lvzb.software@qq.com
*/
public class ConcreteStateA extends State { 

  @Override
  public void Behavior() {
    // 状态A 的业务行为, 及当为该状态下时,能干什么
    // 如:手机在未欠费停机状态下, 能正常拨打电话
    System.out.println("手机在未欠费停机状态下, 能正常拨打电话");
  } 

}

3、具体状态子类B:ConcreteStateB.java

/**
* 具体的状态子类B
* @author lvzb.software@qq.com
*
*/
public class ConcreteStateB extends State { 

  @Override
  public void Behavior() {
    // 状态B 的业务行为, 及当为该状态下时,能干什么
    // 如:手机在欠费停机状态下, 不 能拨打电话
    System.out.println("手机在欠费停机状态下, 不能拨打电话");
  } 

}

4、拥有状态对象的环境类:Context.java

/**
* 环境/上下文类<br/>
* 拥有状态对象,且可以完成状态间的转换 [状态的改变/切换 在环境类中实现]
* @author lvzb.software@qq.com
*
*/
public class Context {
  // 维护一个抽象状态对象的引用
  private State state; 

  /*
  * 模拟手机的话费属性<br/>
  * 环境状态如下:
  * 1>、当 bill >= 0.00$ : 状态正常  还能拨打电话
  * 2>、当 bill < 0.00$ : 手机欠费  不能拨打电话
  */
  private double bill; 

  /**
  * 环境处理函数,调用状态实例行为 完成业务逻辑<br/>
  * 根据不同的状态实例引用 在不同状态下处理不同的行为
  */
  public void Handle(){
    checkState();
    state.Behavior();
  } 

  /**
  * 检查环境状态:状态的改变/切换 在环境类中实现
  */
  private void checkState(){
    if(bill >= 0.00){
      setState(new ConcreteStateA());
    } else {
      setState(new ConcreteStateB());
    }
  } 

  /**
  * 设置环境状态<br/>
  * 私有方法,目的是 让环境的状态由系统环境自身来控制/切换,外部使用者无需关心环境内部的状态
  * @param state
  */
  private void setState(State state){
    this.state = state;
  } 

  public double getBill() {
    return bill;
  } 

  public void setBill(double bill) {
    this.bill = bill;
  }
}

5、测试客户端调用类:Client.java

public class Client { 

  public static void main(String[] args) {
    Context context = new Context();
    context.setBill(5.50);
    System.out.println("当前话费余额:" + context.getBill() + "$");
    context.Handle(); 

    context.setBill(-1.50);
    System.out.println("当前话费余额:" + context.getBill() + "$");
    context.Handle(); 

    context.setBill(50.00);
    System.out.println("当前话费余额:" + context.getBill() + "$");
    context.Handle();
  }
}

6、程序运行结果:

当前话费余额:5.5$ 
手机在未欠费停机状态下, 能正常拨打电话 
当前话费余额:-1.5$ 
手机在欠费停机状态下, 不能拨打电话 
当前话费余额:50.0$ 
手机在未欠费停机状态下, 能正常拨打电话

六、扩展 

状态模式中 关于状态的切换有两种不同的实现方式

方式一:状态的改变/切换  在环境类中实现。  如上面的用例代码Context类中的checkState()方法。

/**
  * 检查环境状态:状态的改变/切换 在环境类中实现
  */
  private void checkState(){
    if(bill >= 0.00){
      setState(new ConcreteStateA());
    } else {
      setState(new ConcreteStateB());
    }
  }

方式二:状态的改变/切换  在具体的状态子类中实现。

实现步骤如下:

1)、在环境类Context类中 初始化一个状态实例对象,并将环境Context对象作为子类状态的构造参数传递到具体的状态子类实例中。

如在Context.java类中

// 设置初始状态
this.state = new ConcreteStateA(this);

2)、 在具体的子类状态类中根据构造进来的context对象,通过调用context对象的属性值进行业务逻辑判断 进行状态的检查和切换。

如在 具体的状态子类ConcreteStateA.java类中:

/**
* 具体的状态子类A
* @author lvzb.software@qq.com
*/
public class ConcreteStateA extends State {
  private Context ctx; 

  public ConcreteStateA(Context context){
    ctx = context;
  } 

  @Override
  public void Behavior() {
    // 状态A 的业务行为, 及当为该状态下时,能干什么
    // 如:手机在未欠费停机状态下, 能正常拨打电话
    System.out.println("手机在未欠费停机状态下, 能正常拨打电话");
    checkState(); 

  } 

  /**
  * 检查状态 是否需要进行状态的转换<br/>
  * 状态的切换由具体状态子类中实现
  */
  private void checkState(){
    if (ctx.getBill() < 0.00) {
      ctx.setState(new ConcreteStateB(ctx));
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java基于代理模式解决红酒经销问题详解

    本文实例讲述了Java基于代理模式解决红酒经销问题.分享给大家供大家参考,具体如下: 一. 模式定义 在代理模式中,有两个对象参与处理同一请求,接收的请求由代理对象委托给真实对象处理,代理对象控制请求的访问,它在客户端应用程序与真实对象之间起到了一个中介桥梁的作用.代理模式使用对象聚合代替继承,有效地降低了软件模块之间的耦合度. 二. 模式举例 1 模式分析 我们借用红酒经销来说明这一模式. 2 代理模式静态类图 3 代码示例 3.1 红酒工厂接口一IRedWine package com.de

  • java 设计模式之State(状态模式)

    java 设计模式之State(状态模式) 在状态模式中,一个类的行为基于它的状态的改变而改变.状态模式归属于行为型模式. 在下面的实例中,我们创建了一个接口State,定义了一个操作方法,两个实现类StartState和StopState.另外,创建了一个上下文类Context,这个类关联到State类.UML类图如下所示: //状态类 public interface State { public void doAction(Context context); } //实现类StartSta

  • Java基于命令模式实现邮局发信功能详解

    本文实例讲述了Java基于命令模式实现邮局发信功能.分享给大家供大家参考,具体如下: 一. 模式定义 命令模式,将来自客户端的请求封建为一个对象,无须了解这个请求激活的动作或有关接受这个请求的处理细节.命令模式的根本目的在于将"请求者"与"实现者"之间解耦. 二. 模式举例 1 模式分析 我们借用邮局发信来说明这一模式. 2 命令模式静态类图 3 代码示例 3.1信件接收者接口一IReceiver package com.demo.receiver; /** * 信

  • Java使用访问者模式解决公司层级结构图问题详解

    本文实例讲述了Java使用访问者模式解决公司层级结构图问题.分享给大家供大家参考,具体如下: 一. 模式定义 访问者模式:是表示一个作用于某对象结构中各个元素的操作,它使用户可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二. 模式举例 1 模式分析 我们借用公司层级结构来说明这一模式. 2 访问者模式静态类图 3 代码示例 3.1 抽象员工一Staff package com.demo.structure; import com.demo.visitor.IVisitor; /**

  • Java使用观察者模式实现气象局高温预警功能示例

    本文实例讲述了Java使用观察者模式实现气象局高温预警功能.分享给大家供大家参考,具体如下: 一.模式定义 观察者模式,又称为发布/订阅模式.观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 二.模式举例 1 模式分析 我们借用气象局高温预警来说明这一模式. 2 观察者模式静态类图 3 代码示例 3.1观察者接口一IObserver package com.demo.observer; import com.demo.subje

  • 轻松掌握Java状态模式

    定义:在状态模式(State Pattern)中,类的行为是基于它的状态改变的. 特点: 1.封装了转换规则. 2.枚举可能的状态,在枚举状态之前需要确定状态种类. 3.将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为. 4.允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块. 5.可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数. 企业及开发和常用框架中的应用: 实例: public class Demo { p

  • Java设计模式之静态代理模式实例分析

    本文实例讲述了Java设计模式之静态代理模式.分享给大家供大家参考,具体如下: 代理模式,可以通过代理可以在原来的基础上附加一些其他的操作.静态代理模式相对比较简单无需再程序运行时动态的进行代理. 静态代理模式的角色: ① 抽象角色:真实对象和代理对象的共同接口.其中声明真实对象和代理对象需要做的事. ② 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用. ③ 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作. 下面提

  • 对比Java设计模式编程中的状态模式和策略模式

    为了能在Java应用程序中正确的使用状态模式和策略模式,开发人员需要清楚地知道这两种模式之间的区别.尽管状态模式和策略模式的结构非常相似,它们又同样遵循开闭原则,都代表着SOLID设计原则的'O',但它们的意图是完全不同的.Java中的策略模式是对一组相关的算法进行封装,给调用方提供了运行时的灵活性.调用方可以在运行时选择不同的算法,而不用修改使用策略的那个Context类.使用策略模式的经典例子包括实现加密算法,压缩算法,以及排序算法.另一方面,状态模式使用一个对象可以在不同的状态下表现出不同

  • Java设计模式之状态模式(State模式)介绍

    State的定义:不同的状态,不同的行为:或者说,每个状态有着相应的行为. 何时使用状态模式 State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了. 不只是根据状态,也有根据属性.如果某个对象的属性不同,对象的行为就不一样,这点在数据库系统中出现频率比较高,我们经常会在一个数据表的尾部,加上property属性含义的字段,用以标识记录中一些特殊

  • Java设计模式之动态代理模式实例分析

    本文实例讲述了Java设计模式之动态代理模式.分享给大家供大家参考,具体如下: 前面介绍了静态代理模式,动态代理比静态代理模式更加强大.它能在程序运行时动态的生成代理对象.所谓动态代理类是在运行时生成的class,在生成它时,你必须提供一组interface给它,则动态代理类就宣称它实现了这些interface.当然,动态代理类就充当一个代理,你不要企图它会帮你干实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作. 动态代理的角色和静态代理的角色一样: ① 抽象角色:

  • Java基于状态模式实现的文档编辑模式切换功能实例

    本文实例讲述了Java基于状态模式实现的文档编辑模式切换功能.分享给大家供大家参考,具体如下: 一 模式定义 状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来就像是改变了其类. 二 模式举例 1 模式分析 我们借用文档编辑模式切换这一案例来说明这一模式. 2 状态模式静态类图 3 代码示例 3.1 创建状态接口一IState package com.demo.state; import com.demo.context.Context; /** * * 状态接口 * * @au

随机推荐