首页 > 代码库 > Java与设计模式-状态模式

Java与设计模式-状态模式

 

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

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

技术分享

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();//关机后功能不再提供	}}

执行实比例如以下:

技术分享

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

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();//关机后功能不再提供	}}


执行例如以下:

技术分享

 

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

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

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

 

 

Java与设计模式-状态模式