程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Java與設計模式-狀態模式

Java與設計模式-狀態模式

編輯: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 {
	/**
	 * 開機狀態下,遙控器按鈕有效
	 */

	@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();//關機後功能不再提供
	}

}

運行如下:

\

總結:控制類持有系統狀態,但控制類不直接處理行為,行為在狀態的實現類中實現;

用戶直接操作控制類,直接和控制類交互,不直接操作狀態實現類,這樣就有一個職責的分離,有利於系統維護。

喜歡的朋友請關注我,謝謝。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved