Java中的有限狀態(tài)機(jī)(設(shè)計(jì)模式——狀態(tài)模式)
Java有限狀態(tài)機(jī) (設(shè)計(jì)模式——狀態(tài)模式)
編寫代碼的時(shí)候,有時(shí)會(huì)遇見較為復(fù)雜的 swith...case... 和 if...else... 語(yǔ)句。
這一刻有時(shí)會(huì)想到狀態(tài)機(jī),用 有限狀態(tài)機(jī) 替換 swith...case... 和 if...else... 可以:
- 降低程序的復(fù)雜度;
- 提高程序的可維護(hù)性;
- 狀態(tài)機(jī)模式體現(xiàn)了開閉原則和單一職責(zé)原則。
每個(gè)狀態(tài)都是一個(gè)子類,增加狀態(tài)就要增加子類;修改狀態(tài)只要修改一個(gè)類就行了。
以上是有限狀態(tài)機(jī)的好處。
其亦有 缺點(diǎn):
- 使用狀態(tài)機(jī)子類會(huì)增多,也就是類膨脹,這點(diǎn)需要程序員在開發(fā)中自己衡量。
狀態(tài)模式定義
Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.
允許對(duì)象在其內(nèi)部狀態(tài)發(fā)生變化時(shí)更改其行為。
看起來(lái)像更改了其類 (這翻譯不好,這里 應(yīng)該是體現(xiàn)了其封裝性:外部的調(diào)用不用知道其內(nèi)部如何實(shí)現(xiàn)狀態(tài)和行為變化的)。
舉個(gè)例子
我們每天都乘坐電梯,電梯有四種狀態(tài): 開門、關(guān)門、運(yùn)行、停止。
| Col1 | 開門 行為 | 關(guān)門 行為 | 運(yùn)行 行為 | 停止 行為 |
|---|---|---|---|---|
| 開門 態(tài) | no | yes | no | no |
| 關(guān)門 態(tài) | yes | no | yes | yes |
| 運(yùn)行 態(tài) | no | no | no | yes |
| 停止 態(tài) | yes | no | yes | no |
LiftState.java
/**
* 定義電梯行為:打開、關(guān)閉、運(yùn)行、停止
*/
public abstract class LiftState {
// 擁有一個(gè)電梯對(duì)象,用于更新電梯當(dāng)前狀態(tài)
protected Lift mLift;
/**
* 通過(guò)構(gòu)造函數(shù)引入電梯的實(shí)例化對(duì)象
*
* @param lift
*/
public LiftState(Lift lift) {
this.mLift = lift;
}
/**
* 行為:打開電梯門
*/
public abstract void open();
/**
* 行為:關(guān)閉電梯門
*/
public abstract void close();
/**
* 行為:電梯運(yùn)行
*/
public abstract void run();
/**
* 行為:電梯停止運(yùn)行
*/
public abstract void stop();
}電梯的四種狀態(tài)
public class OpeningState extends LiftState {
public OpeningState(Lift lift) {
super(lift);
}
@Override
public void open() {
// 執(zhí)行開門動(dòng)作
System.out.println("執(zhí)行開門動(dòng)作");
}
@Override
public void close() {
// 執(zhí)行關(guān)門動(dòng)作
// 1、轉(zhuǎn)化為關(guān)門狀態(tài)
mLift.setState(mLift.getCloseingState());
// 2、關(guān)門
mLift.close();
}
@Override
public void run() {
// do noting
// 開門狀態(tài),不能執(zhí)行運(yùn)行動(dòng)作
}
@Override
public void stop() {
// do noting
// 開門狀態(tài)下,不執(zhí)行停止動(dòng)作
}
}public class ClosingState extends LiftState {
public ClosingState(Lift lift) {
super(lift);
}
@Override
public void open() {
// 執(zhí)行開門動(dòng)作
// 1、變化為開門狀態(tài)
this.mLift.setState(mLift.getOpenningState());
// 2、開門
this.mLift.open();
}
@Override
public void close() {
System.out.println("執(zhí)行關(guān)門動(dòng)作");
}
@Override
public void run() {
// 運(yùn)行動(dòng)作
// 1、運(yùn)行狀態(tài)
this.mLift.setState(mLift.getRunningState());
// 2、運(yùn)行動(dòng)作
this.mLift.run();
}
@Override
public void stop() {
// 停止動(dòng)作
// 1、轉(zhuǎn)化為停止?fàn)顟B(tài)
this.mLift.setState(mLift.getStoppingState());
// 2、停止
this.mLift.stop();
}
}public class RunningState extends LiftState {
public RunningState(Lift lift) {
super(lift);
}
@Override
public void open() {
// do noting
}
@Override
public void close() {
// do noting
}
@Override
public void run() {
// 運(yùn)行動(dòng)作
System.out.println("電梯上下運(yùn)行中...");
}
@Override
public void stop() {
// 停止動(dòng)作
// 1、轉(zhuǎn)化為停止?fàn)顟B(tài)
this.mLift.setState(mLift.getStoppingState());
// 2、停止動(dòng)作
this.mLift.stop();
}
}public class StoppingState extends LiftState {
public StoppingState(Lift lift) {
super(lift);
}
@Override
public void open() {
// 開門動(dòng)作
// 1、開門狀態(tài)
this.mLift.setState(mLift.getOpenningState());
// 2、執(zhí)行開門動(dòng)作
this.mLift.open();
}
@Override
public void close() {
// do noting
}
@Override
public void run() {
// 運(yùn)行動(dòng)作
// 1、運(yùn)行狀態(tài)
this.mLift.setState(mLift.getRunningState());
// 2、運(yùn)行動(dòng)作
this.mLift.run();
}
@Override
public void stop() {
// 電梯停止動(dòng)作
System.out.println("電梯停止運(yùn)行...");
}
}定義電梯類
/**
* 定義電梯類
*/
public class Lift {
//定義出電梯的所有狀態(tài)
private LiftState openningState;
private LiftState closingState;
private LiftState runningState;
private LiftState stoppingState;
// 定義當(dāng)前電梯狀態(tài)
private LiftState mCurState;
/**
* 構(gòu)造方法
*/
public Lift() {
openningState = new OpeningState(this);
closingState = new ClosingState(this);
runningState = new RunningState(this);
stoppingState = new StoppingState(this);
}
/**
* 執(zhí)行開門動(dòng)作
*/
public void open() {
mCurState.open();
}
/**
* 執(zhí)行關(guān)門動(dòng)作
*/
public void close() {
mCurState.close();
}
/**
* 執(zhí)行運(yùn)行動(dòng)作
*/
public void run() {
mCurState.run();
}
/**
* 執(zhí)行停止動(dòng)作
*/
public void stop() {
mCurState.stop();
}
// ##################設(shè)置當(dāng)前電梯狀態(tài)#####################
/**
* 設(shè)置當(dāng)前電梯狀態(tài)
*
* @param state
*/
public void setState(LiftState state) {
this.mCurState = state;
}
// ###################獲取電梯的全部狀態(tài)####################
public LiftState getOpenningState() {
return openningState;
}
public LiftState getCloseingState() {
return closingState;
}
public LiftState getRunningState() {
return runningState;
}
public LiftState getStoppingState() {
return stoppingState;
}
}運(yùn)行
public static void main(String[] args) {
Lift lift = new Lift();
lift.setState(new ClosingState(lift));
lift.open();
lift.close();
lift.run();
lift.stop();
}運(yùn)行結(jié)果
執(zhí)行開門動(dòng)作
執(zhí)行關(guān)門動(dòng)作
電梯上下運(yùn)行中...
電梯停止運(yùn)行...
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
JAVA區(qū)間值判斷[10,20)的實(shí)現(xiàn)
本文主要介紹了JAVA區(qū)間值判斷[10,20)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09
MyBatis游標(biāo)Cursor在Oracle數(shù)據(jù)庫(kù)上的測(cè)試方式
這篇文章主要介紹了MyBatis游標(biāo)Cursor在Oracle數(shù)據(jù)庫(kù)上的測(cè)試方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Netty分布式FastThreadLocal的set方法實(shí)現(xiàn)邏輯剖析
這篇文章主要為大家介紹了Netty分布式FastThreadLocal的set方法實(shí)現(xiàn)邏輯剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03
java多線程中的生產(chǎn)者和消費(fèi)者隊(duì)列詳解
這篇文章主要介紹了java多線程中的生產(chǎn)者和消費(fèi)者隊(duì)列詳解,隊(duì)列,是一種數(shù)據(jù)結(jié)構(gòu),除了優(yōu)先級(jí)隊(duì)列和LIFO隊(duì)列外,隊(duì)列都是以FIFO(先進(jìn)先出)的方式對(duì)各個(gè)元素進(jìn)行排序的,需要的朋友可以參考下2024-01-01
深入dom4j使用selectSingleNode方法報(bào)錯(cuò)分析
本篇文章是對(duì)dom4j使用selectSingleNode方法報(bào)錯(cuò)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
SpringBoot開發(fā)存儲(chǔ)服務(wù)器實(shí)現(xiàn)過(guò)程詳解
這篇文章主要為大家介紹了SpringBoot開發(fā)存儲(chǔ)服務(wù)器實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Java數(shù)據(jù)庫(kù)連接池的幾種配置方法(以MySQL數(shù)據(jù)庫(kù)為例)
這篇文章主要介紹了Java數(shù)據(jù)庫(kù)連接池的幾種配置方法(以MySQL數(shù)據(jù)庫(kù)為例) 的相關(guān)資料,需要的朋友可以參考下2016-07-07

