Java与设计模式-状态模式

Posted yayun0516

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 {
	/**
	 * 开机状态下,遥控器按钮有效
	 */

	@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 {
	/**
	 * 关机状态下,所有按钮无效
	 */

	@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与设计模式-状态模式的主要内容,如果未能解决你的问题,请参考以下文章

Java与设计模式-状态模式

Java 设计模式之状态学习与掌握

Java 设计模式之状态学习与掌握

Java 设计模式之状态学习与掌握

Java与设计模式-状态模式

Java 设计模式 状态模式