JAVA设计模式之 状态模式【State Pattern】

一、概述

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

二、适用场景

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

三、UML类图

四、参与者

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

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

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

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

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

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

五、用例学习

1、抽象状态类:State.java

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

}

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

/**
 * 具体的状态子类A
 * @author  [email protected]
 */
public class ConcreteStateA extends State {

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

}

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

/**
 * 具体的状态子类B
 * @author  [email protected]
 *
 */
public class ConcreteStateB extends State {

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

}

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

/**
 * 环境/上下文类<br/>
 * 拥有状态对象,且可以完成状态间的转换 [状态的改变/切换 在环境类中实现]
 * @author  [email protected]
 *
 */
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  [email protected]
 */
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));
		}
	}
}
时间: 2024-08-03 11:23:28

JAVA设计模式之 状态模式【State Pattern】的相关文章

[设计模式] 20 状态模式 State Pattern

在GOF的<设计模式:可复用面向对象软件的基础>一书中对状态模式是这样说的:允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类.状态模式的重点在于状态转换,很多时候,对于一个对象的状态,我们都是让这个对象包含一个状态的属性,这个状态属性记录着对象的具体状态,根据状态的不同使用分支结构来执行不同的功能,就像上面的代码那样处理:就像上面说的,类中存在大量的结构类似的分支语句,变得难以维护和理解.状态模式消除了分支语句,就像工厂模式消除了简单工厂模式的分支语句一样,将状态处理分散

设计模式 - 状态模式(state pattern) 详解

状态模式(state pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 状态模式(state pattern): 允许对象在内部状态改变时改变它的行为, 对象看起来好像修改了它的类. 建立Context类, 包含多个具体状态(concrete state)类的组合, 根据状态的不同调用具体的方法, state.handle(), 包含set\get方法改变状态. 状态接口(state interface), 包含抽象方法handle(),

设计模式 - 状态模式(state pattern) 未使用状态模式 详解

状态模式(state pattern) 未使用状态模式 详解 本文地址: http://blog.csdn.net/caroline_wendy 状态模式可以控制状态的转换, 未使用设计模式时, 程序会非常繁杂. 具体方法: 1. 状态转换类. /** * @time 2014年7月11日 */ package state; /** * @author C.L.Wang * */ public class GumballMachine { final static int SOLD_OUT =

设计模式之状态模式(State)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

设计模式(行为型)之状态模式(State Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之模板方法模式(Template Method Pattern)>http://blog.csdn.net/yanbober/article/details/45501715 概述 状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题.当系统中

JAVA设计模式:状态模式

声明:转载请说明来源:http://www.cnblogs.com/pony1223/p/7518226.html 一.引出状态模式 假设我们现在有一个糖果机项目,那么我们知道正常一般糖果机提供给用户的行为有这么几种:投入硬币.转动曲柄.退出硬币几种行为:那么糖果机呢一般有这几中状态,待机状态.持有硬币的准备状态.运行状态即正在售出状态和初始状态 这么几种正常状态. 我们发现处于不同状态的时候,持有的行为是不一样的,图如下: 如果我们采用传统的方法来写代码,那么在投入硬币这个行为操作的时候,我们

设计模式 ( 十七) 状态模式State(对象行为型)

1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ellse语句来做状态判断来进行不同情况的处理.但是对复杂状态的判断就显得“力不从心了”.随着增加新的状态或者修改一个状体(if else(或switch case)语句的增多或者修改)可能会引起很大的修改,而程序的可读性,扩展性也会变得很弱.维护也会很麻烦.那么我就考虑只修改自身状态的模式. 例子1:按钮来控制一个电梯的状态,一个电梯开们,关门,停,

Java设计模式之状态模式

本文继续介绍23种设计模式系列之策略模式. 何时使用 State模式在实际使用中比较多,适合"状态"的切换.因为我们经常会使用If else if else 进行状态切换,如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了. 这里要阐述的是"开关切换状态" 和" 一般的状态判断"是有一些区别的," 一般的状态判断"也是有 if..elseif结构,例如: if (which==1) state=&q

状态模式(State Pattern)

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化. 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理. 抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为. 具体状态(Concrete State