Java与设计模式-状态模式

 

概念:状态模式把所研究的对象的行为包装在不同的状态对象里。每个状态对象都属于一个抽象状态类的一个子类。

状态模式的意图是让一个对象在其内部状态改变的时候。其行为也随之改变,也就是不同状态相应不同的行为。状态模式的示意性类图例如以下所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

UML类图:Context:能够理解成控制类

State是状态接口

ConcreteStateA和ConcreteStateB能够觉得是接口的实现,也就是详细的状态实现类。

使用场景:对象的状态决定对象的行为,在执行时依据状态动态调整对象的行为。

代码中有复杂的if else推断。且这些分支推断和状态有关系。

实际场景:(1)电视开关机状态,电视开机状态下才干够进行各种操作,关机状态下,不能进行各项操作。

                  (2)WIFI状态,WIFI开状态下能够连接WIFI,关闭状态不可进行操作。

                  (3)登录状态,这个在开发中较为经常使用。一般在进入系统实现分享转发等操作时要先推断用户的登录状态,若已经登录则可进行操作。否则提示用户登录。

我们来实现场景1.

首先创建一个状态接口(相应UML类图中的State接口):

package com.state.demo;

public interface TvState {
	/**
	 * 电视状态的接口,里面提供四种方法
	 */
	void nextChanel();
	void preChanel();
	void turnUp();
	void turnDown();

}

接下来两个实现类(相应UML类图中ConcreteStateA):

package com.state.demo;

public class PowerOnState implements TvState {
	/**
	 * 开机状态下,遥控器button有效
	 */

	@Override
	public void nextChanel() {

		System.out.println("---------下一频道-----------------------");
	}

	@Override
	public void preChanel() {
		System.out.println("---------上一频道-----------------------");
	}

	@Override
	public void turnUp() {
		System.out.println("---------音量增大-----------------------");
	}

	@Override
	public void turnDown() {
		System.out.println("---------音量减小-----------------------");
	}

}

实现类2(相应UML类图中ConcreteStateB):

package com.state.demo;

public class PowerOffState implements TvState {
	/**
	 * 关机状态下。全部button无效
	 */

	@Override
	public void nextChanel() {
		System.out.println("---------关机状态不可用。请先开机-----------------------");
	}

	@Override
	public void preChanel() {
		System.out.println("---------关机状态不可用,请先开机-----------------------");
	}

	@Override
	public void turnUp() {
		System.out.println("---------关机状态不可用。请先开机-----------------------");
	}

	@Override
	public void turnDown() {
		System.out.println("---------关机状态不可用。请先开机-----------------------");
	}

}

接下来控制类(相应UML类图中Context):

package com.state.demo;

public class TvController {

	TvState tvState=null;
	public void setTvState(TvState tvState) {
		this.tvState = tvState;
	}
	/**
	 * 开机
	 */
	public void turnOnTv(){

		setTvState(new PowerOnState());
		System.out.println("--------开机啦---------------");
	}
	/**
	 * 关机
	 */
	public void turnOffTv(){

		setTvState(new PowerOffState());
		System.out.println("--------关机啦---------------");
	}
	/**
	 * 下一频道
	 */
	public void nextChanel(){
		tvState.nextChanel();
	}

	public void preChanel(){
		tvState.preChanel();
	}

	public void turnUp(){
		tvState.turnUp();
	}
	public void turnDown(){
		tvState.turnDown();
	}
}

最后,编写一个測试类,測试以上代码:

package com.state.demo;

public class TestClass {

	public static void main(String[] args) {

		TvController tvController=new TvController();//创建一个控制类
		tvController.turnOnTv();//首先开机
		tvController.nextChanel();
		tvController.turnDown();
		tvController.turnOffTv();//关机

		tvController.turnDown();//关机后功能不再提供
	}

}

执行实比例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

这里有些逻辑小问题,就是在已经开机的状态下,用户再次调用开机要进行提示。这时我们能够在控制类中增加例如以下代码;

package com.state.demo;

public class TvController {
	private boolean isTvOn=false;
	TvState tvState=null;
	public void setTvState(TvState tvState) {
		this.tvState = tvState;
	}
	/**
	 * 开机
	 */
	public void turnOnTv(){
		if(!isTvOn){
			isTvOn=true;
			setTvState(new PowerOnState());
			System.out.println("--------开机啦---------------");
		}else{
			isTvOn=true;
			System.out.println("--------已经开机了,不要再按了---------------");
		}

	}
	/**
	 * 关机
	 */
	public void turnOffTv(){
		if(isTvOn){
			isTvOn=false;
		setTvState(new PowerOffState());
		System.out.println("--------关机啦---------------");
		}else{
			isTvOn=false;
			System.out.println("-------已经关机啦,不要再按了---------------");
		}
	}
	/**
	 * 下一频道
	 */
	public void nextChanel(){
		tvState.nextChanel();
	}

	public void preChanel(){
		tvState.preChanel();
	}

	public void turnUp(){
		tvState.turnUp();
	}
	public void turnDown(){
		tvState.turnDown();
	}
}

做一个开机标识,每次调用方法之前进行推断就可以。

这时再次执行測试类:

package com.state.demo;

public class TestClass {

	public static void main(String[] args) {

		TvController tvController=new TvController();//创建一个控制类
		tvController.turnOnTv();//首先开机
		tvController.turnOnTv();//首先开机
		tvController.nextChanel();
		tvController.turnDown();
		tvController.turnOffTv();//关机
		tvController.turnOffTv();//关机

		tvController.turnDown();//关机后功能不再提供
	}

}

执行例如以下:

总结:控制类持有系统状态,但控制类不直接处理行为,行为在状态的实现类中实现;

          用户直接操作控制类,直接和控制类交互,不直接操作状态实现类,这样就有一个职责的分离,有利于系统维护。

喜欢的朋友请关注我,谢谢。

时间: 2024-10-03 13:46:39

Java与设计模式-状态模式的相关文章

设计模式 状态模式 以自动售货机为例

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/26350617 状态模式给了我眼前一亮的感觉啊,值得学习~ 先看定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类.定义又开始模糊了,理一下,当对象的内部状态改变时,它的行为跟随状态的改变而改变了,看起来好像重新初始化了一个类似的. 下面使用个例子来说明状态模式的用法,现在有个自动售货机的代码需要我们来写,状态图如下: 分析一个这个状态图: a.包含4个状态(

设计模式 - 状态模式(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 =

14. 星际争霸之php设计模式--状态模式

题记==============================================================================本php设计模式专辑来源于博客(jymoz.com),现在已经访问不了了,这一系列文章是我找了很久才找到完整的,感谢作者jymoz的辛苦付出哦! 本文地址:http://www.cnblogs.com/davidhhuan/p/4248198.html============================================

【C#设计模式-状态模式】

一.状态模式的定义:状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化. 二.状态模式的意图:允许一个对象在其内部状态改变时改变它的行为. 三.状态模式的适用场景: 1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为. 2.一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态. 四.状态模式的实现: /// <summary> /// 定义接口,封装Context对象在特定

java设计模式----状态模式

状态模式: 允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类. 要点: 1.状态模式允许一个对象基于内部状态而拥有不同的行为 2.和程序状态机(PSM)不同,状态模式用类代表状态 3.Context会将行为委托给当前状态对象 4.通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了 5.状态模式和策略模式有相同的类图,但是它们的意思不同 6.策略模式通常会用行为或算法来配置Context类 7.状态模式允许Context随着状态的改变而改变行为 8.状态改变可以由Sta

JAVA 设计模式 状态模式

用途 状态模式 (State) 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式是一种行为型模式. 结构 图-状态模式结构图 State : 定义一个接口以封装与 Context 的一个特定状态相关的行为. abstract class State {    public abstract void Handle(Context context);} ConcreteState : 每一个子类实现一个与 Context 的一个状态相关的行为. class Con

Java设计模式——状态模式(State)

1979年在湖北出土的曾侯乙编钟,每一只钟都能发出不同的音. 用面向对象的语言来讲,编钟有能够动态变化的属性,也就是它所能发出的声音.编钟的这种属性叫做状态,而编钟被叫做有状态的对象.编钟所能发出的声音是由敲击的那一只钟决定,而钟的数目个每一只钟的状态是事先确定的. 很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的对象. 状态模式的类图如下: 状态模式设计的角色有: 抽象状态角色(State):定义一个接口,用以封装环境对象的一个特定的状态所对

设计模式-状态模式(State Pattern)

本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 状态模式简介 状态模式允许一个对象在其内部状态改变的时候改变它的行为,他的内部会存着好几种状态,在当前状态发生变化是,这个对象执行和之前相同的操作也会有不同的作用效果. 状态模式的定义和基本结构 定义:状态模式允许一个对象在其内部状态改变的时候改变它的行为,就像变成了另一个对象一样. 一张来自<Head First>的结构图 Context:这个类里面包含了很多种状态类,当前状态不同时,这个