摘要:為了實(shí)現(xiàn)這個(gè)正義偷笑又合理的訴求,你得先學(xué)會(huì)今天要介紹的設(shè)計(jì)模式,因?yàn)槟銈児镜倪@個(gè)流程可能就是用今天這個(gè)模式設(shè)計(jì)的。狀態(tài)模式對(duì)開(kāi)閉原則的支持并不太好,新增狀態(tài)時(shí),不僅得增加狀態(tài)類,還得修改原來(lái)已經(jīng)有的狀態(tài),讓之前的狀態(tài)切換到新增的狀態(tài)。
一、定義你是否經(jīng)常請(qǐng)(偷)假(懶)?是不是對(duì)公司萬(wàn)惡的請(qǐng)假申請(qǐng)流程深惡痛絕。有沒(méi)有想過(guò)偷偷改造這個(gè)萬(wàn)惡的系統(tǒng),從 申請(qǐng)->項(xiàng)目經(jīng)理審批->部門審批->老板審批->完成? 偷偷改為? 申請(qǐng)->完成。為了實(shí)現(xiàn)這個(gè)正義[偷笑]又合理的訴求,你得先學(xué)會(huì)今天要介紹的設(shè)計(jì)模式,因?yàn)槟銈児镜倪@個(gè)流程可能就是用今天這個(gè)模式設(shè)計(jì)的。來(lái)看看這個(gè)設(shè)計(jì)模式是怎么來(lái)抽象這類流程性的業(yè)務(wù)的。
狀態(tài)模式【百度百科】:當(dāng)一個(gè)對(duì)象的內(nèi)在狀態(tài)改變時(shí)允許改變其行為,這個(gè)對(duì)象看起來(lái)像是改變了其類。
這個(gè)定義看起來(lái)莫名其妙,咋一看,我也不知道它要表達(dá)什么。個(gè)人的理解:某個(gè)對(duì)象是有狀態(tài)的,比如我們上面的請(qǐng)假流程,它處于項(xiàng)目經(jīng)理狀態(tài),那項(xiàng)目經(jīng)理可以審核你的請(qǐng)假申請(qǐng),到了老板處理環(huán)節(jié),老板直接把你申請(qǐng)單刪了【哈哈】。在這不同的狀態(tài)是可以有不同的操作的。不知道你看懂了定義了沒(méi)??什么?沒(méi)看懂,那就直接看下面的代碼咯,talk is cheap show me the code。
二、UML圖
UML圖如下,我直接把請(qǐng)假這個(gè)例子畫(huà)了個(gè)UML圖,如下,有一個(gè)公共的State抽象類,里面定義了兩個(gè)變量來(lái)保存當(dāng)前狀態(tài)的狀態(tài)Code,狀態(tài)Name,下面為具體的狀態(tài),分別為:AppState(申請(qǐng)狀態(tài)),ProjectManagesState(項(xiàng)目經(jīng)理審核狀態(tài)),BossState(老板審核狀態(tài)),通過(guò)Context來(lái)提供給客戶端使用。
具體代碼實(shí)現(xiàn)如下:
1、狀態(tài)抽象類
package com.design.state;
public abstract class State {
private String stateCode;
private String stateName;
//往下個(gè)環(huán)節(jié)走
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、定義具體的狀態(tài)
package com.design.state;
/**
* 申請(qǐng)狀態(tài)
*/
public class AppState extends State{
public AppState(){
super("Apply", "申請(qǐng)環(huán)節(jié)");
}
@Override
public void toNextState(Context context) {
//申請(qǐng)狀態(tài),這里可以做該狀態(tài)下的操作
System.out.println("我是申請(qǐng)人,我申請(qǐng)休假,下一個(gè)環(huán)節(jié)是項(xiàng)目經(jīng)理審核!!");
//直接進(jìn)去項(xiàng)目經(jīng)理審核狀態(tài)
context.setCurrentState(new ProjectManagesState());
}
}
package com.design.state;
/**
* 項(xiàng)目經(jīng)理審核狀態(tài)
*/
public class ProjectManagesState extends State{
public ProjectManagesState(){
super("ProjectManages", "項(xiàng)目經(jīng)理審核環(huán)節(jié)");
}
@Override
public void toNextState(Context context) {
//項(xiàng)目經(jīng)理審核狀態(tài),這里可以做該狀態(tài)下的操做
System.out.println("我是項(xiàng)目經(jīng)理,那臭小子一定有跑去面試了,哎,幫他一把,同意了,下個(gè)環(huán)節(jié)讓老板審去");
//直接進(jìn)去老板審核狀態(tài)
context.setCurrentState(new BossState());
}
}
package com.design.state;
/**
* 老板審核狀態(tài)
*/
public class BossState extends State{
public BossState(){
super("Boss Audit", "老板審核環(huán)節(jié)");
}
@Override
public void toNextState(Context context) {
//項(xiàng)目經(jīng)理審核狀態(tài),這里可以做該狀態(tài)下的操做
System.out.println("我是老板,我同意你請(qǐng)假了!!!流程結(jié)束!");
}
}
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、寫好了,看下怎么調(diào)用
package com.design.state;
public class TestMain {
public static void main(String[] args) {
//創(chuàng)建申請(qǐng)休假單
Context context = new Context(new AppState());
System.out.println("狀態(tài):"+context.getCurrentState().getStateName());
//提交申請(qǐng)
context.toNextState();
System.out.println("狀態(tài):"+context.getCurrentState().getStateName());
//項(xiàng)目經(jīng)理審核
context.toNextState();
System.out.println("狀態(tài):"+context.getCurrentState().getStateName());
//老板審核
context.toNextState();
}
}
5、執(zhí)行結(jié)果
(1)、將與特定狀態(tài)相關(guān)的行為局部化,將不同狀態(tài)的行為分割開(kāi)來(lái)。
(2)、把狀態(tài)轉(zhuǎn)移邏輯分布到具體狀態(tài)類中,減少相互間的依賴。
看不懂這兩個(gè)優(yōu)點(diǎn)??OK,我們來(lái)解釋下,先來(lái)看看,不用狀態(tài)模式,我們代碼會(huì)怎么寫?
package com.design.state;
public class StateChange {
private int state = 0;
private final static int APPLY=0; //申請(qǐng)狀態(tài)
private final static int PROJECTMANAGES=1;//項(xiàng)目經(jīng)理審核狀態(tài)
private final static int BOSS=2;//老板審核狀態(tài)
private final static int FINISH=3;//流程結(jié)束狀態(tài)
public void toNextState(){
switch (state){
case 0:
//申請(qǐng)狀態(tài),做點(diǎn)操作
System.out.println("寫申請(qǐng)書(shū)!!!");
//進(jìn)入項(xiàng)目經(jīng)理審核狀態(tài)
state = PROJECTMANAGES;
break;
case 1:
System.out.println("項(xiàng)目經(jīng)理審核,同意你申請(qǐng)了");
//進(jìn)入老板審核狀態(tài)
state = BOSS;
break;
case 2:
System.out.println("我是老板,同意你申請(qǐng)了");
//進(jìn)入結(jié)束狀態(tài)
state = FINISH;
break;
default:
break;
}
}
}
你是不是寫的跟我一樣呢??有沒(méi)有注意到,所有的操作,無(wú)論是哪個(gè)狀態(tài)的操作都是在這個(gè)類中完成的,而使用狀態(tài)模式,不同狀態(tài)下的行為是定義在不同的狀態(tài)類下的。這就是前面說(shuō)的優(yōu)點(diǎn)1。
我們狀態(tài)切換是通過(guò)switch來(lái)判斷狀態(tài),再?zèng)Q定下一個(gè)狀態(tài)的,而在狀態(tài)模式下,切換到下一個(gè)狀態(tài),是在具體的狀態(tài)類下進(jìn)行的,可以減少if之類的判斷邏輯。這就是優(yōu)點(diǎn)2。
2、缺點(diǎn)(1)、狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜,如果使用不當(dāng)將導(dǎo)致程序結(jié)構(gòu)和代碼的混亂。?
(2)、狀態(tài)模式對(duì)"開(kāi)閉原則"的支持并不太好,新增狀態(tài)時(shí),不僅得增加狀態(tài)類,還得修改原來(lái)已經(jīng)有的狀態(tài),讓之前的狀態(tài)切換到新增的狀態(tài)。
六、總結(jié)說(shuō)明狀態(tài)模式將原來(lái)通過(guò)判斷實(shí)現(xiàn)的狀態(tài)切換分散到各具體狀態(tài)類中,比如上面切換到“老板審核狀態(tài)”,是在“項(xiàng)目經(jīng)理審核狀態(tài)”中進(jìn)行的,當(dāng)狀態(tài)比較多的情況,不容易理清各狀態(tài)切換關(guān)系。同時(shí)它有將各狀態(tài)的操作獨(dú)立到狀態(tài)類中,方便測(cè)試,還有分隔開(kāi)各不同操作,便于閱讀代碼。實(shí)際運(yùn)用中可根據(jù)自己的場(chǎng)景進(jìn)行權(quán)衡。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/7849.html
摘要:什么是狀態(tài)模式狀態(tài)模式對(duì)象行為是基于狀態(tài)來(lái)改變的。原文地址設(shè)計(jì)模式手冊(cè)之狀態(tài)模式優(yōu)缺點(diǎn)優(yōu)點(diǎn)封裝了轉(zhuǎn)化規(guī)則,對(duì)于大量分支語(yǔ)句,可以考慮使用狀態(tài)類進(jìn)一步封裝。 1. 什么是狀態(tài)模式? 狀態(tài)模式:對(duì)象行為是基于狀態(tài)來(lái)改變的。 內(nèi)部的狀態(tài)轉(zhuǎn)化,導(dǎo)致了行為表現(xiàn)形式不同。所以,用戶在外面看起來(lái),好像是修改了行為。 Webpack4系列教程(17篇) + 設(shè)計(jì)模式手冊(cè)(16篇):GitHub地址 博...
摘要:什么是狀態(tài)模式狀態(tài)模式對(duì)象行為是基于狀態(tài)來(lái)改變的。原文地址設(shè)計(jì)模式手冊(cè)之狀態(tài)模式優(yōu)缺點(diǎn)優(yōu)點(diǎn)封裝了轉(zhuǎn)化規(guī)則,對(duì)于大量分支語(yǔ)句,可以考慮使用狀態(tài)類進(jìn)一步封裝。 1. 什么是狀態(tài)模式? 狀態(tài)模式:對(duì)象行為是基于狀態(tài)來(lái)改變的。 內(nèi)部的狀態(tài)轉(zhuǎn)化,導(dǎo)致了行為表現(xiàn)形式不同。所以,用戶在外面看起來(lái),好像是修改了行為。 Webpack4系列教程(17篇) + 設(shè)計(jì)模式手冊(cè)(16篇):GitHub地址 博...
摘要:而享元模式的核心就是運(yùn)用共享技術(shù)來(lái)有效支持大量細(xì)粒度的對(duì)象。享元模式要求將對(duì)象的屬性劃分為內(nèi)部狀態(tài)和外部狀態(tài),所以在了解享元模式之前我們先要了解兩個(gè)概念內(nèi)部狀態(tài)外部狀態(tài)。一般情況下在這四種情況下應(yīng)該考慮使用享元模式。 享元模式(flyweight)是一種用于性能優(yōu)化的模式,之所以用fly其意為蠅量級(jí)。而享元模式的核心就是運(yùn)用共享技術(shù)來(lái)有效支持大量細(xì)粒度的對(duì)象。雖然面向?qū)ο罂梢苑浅7奖愕?..
摘要:類圖相關(guān)的設(shè)計(jì)模式享元模式和代理模式當(dāng)代理模式消耗性能比較大的時(shí)候,就可以用享元模式享元模式和單例模式容器單例,享元模式就是復(fù)用對(duì)象的思想。源碼中的享元模式源碼地址享元模式參考慕課網(wǎng)設(shè)計(jì)模式精講設(shè)計(jì)模式讀書(shū)筆記享元模式 0x01.定義與類型 定義:提供了減少對(duì)象數(shù)量從而改善應(yīng)用所需的對(duì)象結(jié)構(gòu)的方法,系統(tǒng)使用少量對(duì)象,而且這些都比較相似,狀態(tài)變化小,可以實(shí)現(xiàn)對(duì)象的多次復(fù)用。 運(yùn)用共享技...
閱讀 2011·2019-08-29 16:27
閱讀 1379·2019-08-29 16:14
閱讀 3380·2019-08-29 14:18
閱讀 3466·2019-08-29 13:56
閱讀 1262·2019-08-29 11:13
閱讀 2134·2019-08-28 18:19
閱讀 3451·2019-08-27 10:57
閱讀 2288·2019-08-26 11:39