摘要:為了實現這個正義偷笑又合理的訴求,你得先學會今天要介紹的設計模式,因為你們公司的這個流程可能就是用今天這個模式設計的。狀態模式對開閉原則的支持并不太好,新增狀態時,不僅得增加狀態類,還得修改原來已經有的狀態,讓之前的狀態切換到新增的狀態。
一、定義你是否經常請(偷)假(懶)?是不是對公司萬惡的請假申請流程深惡痛絕。有沒有想過偷偷改造這個萬惡的系統,從 申請->項目經理審批->部門審批->老板審批->完成? 偷偷改為? 申請->完成。為了實現這個正義[偷笑]又合理的訴求,你得先學會今天要介紹的設計模式,因為你們公司的這個流程可能就是用今天這個模式設計的。來看看這個設計模式是怎么來抽象這類流程性的業務的。
狀態模式【百度百科】:當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。
這個定義看起來莫名其妙,咋一看,我也不知道它要表達什么。個人的理解:某個對象是有狀態的,比如我們上面的請假流程,它處于項目經理狀態,那項目經理可以審核你的請假申請,到了老板處理環節,老板直接把你申請單刪了【哈哈】。在這不同的狀態是可以有不同的操作的。不知道你看懂了定義了沒??什么?沒看懂,那就直接看下面的代碼咯,talk is cheap show me the code。
二、UML圖
UML圖如下,我直接把請假這個例子畫了個UML圖,如下,有一個公共的State抽象類,里面定義了兩個變量來保存當前狀態的狀態Code,狀態Name,下面為具體的狀態,分別為:AppState(申請狀態),ProjectManagesState(項目經理審核狀態),BossState(老板審核狀態),通過Context來提供給客戶端使用。
具體代碼實現如下:
1、狀態抽象類
package com.design.state;
public abstract class State {
private String stateCode;
private String stateName;
//往下個環節走
public abstract void toNextState(Context context);
public State(String stateCode, String stateName){
this.stateCode = stateCode;
this.stateName = stateName;
}
public String getStateCode() {
return stateCode;
}
public void setStateCode(String stateCode) {
this.stateCode = stateCode;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
}
2、定義具體的狀態
package com.design.state;
/**
* 申請狀態
*/
public class AppState extends State{
public AppState(){
super("Apply", "申請環節");
}
@Override
public void toNextState(Context context) {
//申請狀態,這里可以做該狀態下的操作
System.out.println("我是申請人,我申請休假,下一個環節是項目經理審核!!");
//直接進去項目經理審核狀態
context.setCurrentState(new ProjectManagesState());
}
}
package com.design.state;
/**
* 項目經理審核狀態
*/
public class ProjectManagesState extends State{
public ProjectManagesState(){
super("ProjectManages", "項目經理審核環節");
}
@Override
public void toNextState(Context context) {
//項目經理審核狀態,這里可以做該狀態下的操做
System.out.println("我是項目經理,那臭小子一定有跑去面試了,哎,幫他一把,同意了,下個環節讓老板審去");
//直接進去老板審核狀態
context.setCurrentState(new BossState());
}
}
package com.design.state;
/**
* 老板審核狀態
*/
public class BossState extends State{
public BossState(){
super("Boss Audit", "老板審核環節");
}
@Override
public void toNextState(Context context) {
//項目經理審核狀態,這里可以做該狀態下的操做
System.out.println("我是老板,我同意你請假了!!!流程結束!");
}
}
3、上下文類
package com.design.state;
public class Context {
private State currentState;
public Context(State state){
currentState = state;
}
public void toNextState(){
currentState.toNextState(this);
};
public State getCurrentState() {
return currentState;
}
public void setCurrentState(State currentState) {
this.currentState = currentState;
}
}
4、寫好了,看下怎么調用
package com.design.state;
public class TestMain {
public static void main(String[] args) {
//創建申請休假單
Context context = new Context(new AppState());
System.out.println("狀態:"+context.getCurrentState().getStateName());
//提交申請
context.toNextState();
System.out.println("狀態:"+context.getCurrentState().getStateName());
//項目經理審核
context.toNextState();
System.out.println("狀態:"+context.getCurrentState().getStateName());
//老板審核
context.toNextState();
}
}
5、執行結果
(1)、將與特定狀態相關的行為局部化,將不同狀態的行為分割開來。
(2)、把狀態轉移邏輯分布到具體狀態類中,減少相互間的依賴。
看不懂這兩個優點??OK,我們來解釋下,先來看看,不用狀態模式,我們代碼會怎么寫?
package com.design.state;
public class StateChange {
private int state = 0;
private final static int APPLY=0; //申請狀態
private final static int PROJECTMANAGES=1;//項目經理審核狀態
private final static int BOSS=2;//老板審核狀態
private final static int FINISH=3;//流程結束狀態
public void toNextState(){
switch (state){
case 0:
//申請狀態,做點操作
System.out.println("寫申請書!!!");
//進入項目經理審核狀態
state = PROJECTMANAGES;
break;
case 1:
System.out.println("項目經理審核,同意你申請了");
//進入老板審核狀態
state = BOSS;
break;
case 2:
System.out.println("我是老板,同意你申請了");
//進入結束狀態
state = FINISH;
break;
default:
break;
}
}
}
你是不是寫的跟我一樣呢??有沒有注意到,所有的操作,無論是哪個狀態的操作都是在這個類中完成的,而使用狀態模式,不同狀態下的行為是定義在不同的狀態類下的。這就是前面說的優點1。
我們狀態切換是通過switch來判斷狀態,再決定下一個狀態的,而在狀態模式下,切換到下一個狀態,是在具體的狀態類下進行的,可以減少if之類的判斷邏輯。這就是優點2。
2、缺點(1)、狀態模式的結構與實現都較為復雜,如果使用不當將導致程序結構和代碼的混亂。?
(2)、狀態模式對"開閉原則"的支持并不太好,新增狀態時,不僅得增加狀態類,還得修改原來已經有的狀態,讓之前的狀態切換到新增的狀態。
六、總結說明狀態模式將原來通過判斷實現的狀態切換分散到各具體狀態類中,比如上面切換到“老板審核狀態”,是在“項目經理審核狀態”中進行的,當狀態比較多的情況,不容易理清各狀態切換關系。同時它有將各狀態的操作獨立到狀態類中,方便測試,還有分隔開各不同操作,便于閱讀代碼。實際運用中可根據自己的場景進行權衡。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7849.html
摘要:什么是狀態模式狀態模式對象行為是基于狀態來改變的。原文地址設計模式手冊之狀態模式優缺點優點封裝了轉化規則,對于大量分支語句,可以考慮使用狀態類進一步封裝。 1. 什么是狀態模式? 狀態模式:對象行為是基于狀態來改變的。 內部的狀態轉化,導致了行為表現形式不同。所以,用戶在外面看起來,好像是修改了行為。 Webpack4系列教程(17篇) + 設計模式手冊(16篇):GitHub地址 博...
摘要:什么是狀態模式狀態模式對象行為是基于狀態來改變的。原文地址設計模式手冊之狀態模式優缺點優點封裝了轉化規則,對于大量分支語句,可以考慮使用狀態類進一步封裝。 1. 什么是狀態模式? 狀態模式:對象行為是基于狀態來改變的。 內部的狀態轉化,導致了行為表現形式不同。所以,用戶在外面看起來,好像是修改了行為。 Webpack4系列教程(17篇) + 設計模式手冊(16篇):GitHub地址 博...
閱讀 2001·2019-08-29 16:27
閱讀 1370·2019-08-29 16:14
閱讀 3372·2019-08-29 14:18
閱讀 3455·2019-08-29 13:56
閱讀 1252·2019-08-29 11:13
閱讀 2118·2019-08-28 18:19
閱讀 3439·2019-08-27 10:57
閱讀 2273·2019-08-26 11:39