最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解Java設(shè)計(jì)模式之狀態(tài)模式

 更新時(shí)間:2021年11月07日 14:29:22   作者:一指流砂~  
這篇文章主要介紹了JAVA設(shè)計(jì)模式之職責(zé)鏈模式的的相關(guān)資料,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解

一、什么是狀態(tài)模式

定義:當(dāng)一個(gè)對(duì)象的內(nèi)在狀態(tài)改變時(shí)允許改變其行為,這個(gè)對(duì)象看起來(lái)像是改變了其類(lèi)。

主要解決:當(dāng)控制一個(gè)對(duì)象狀態(tài)的條件表達(dá)式過(guò)于復(fù)雜時(shí)的情況。把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類(lèi)中,可以把復(fù)雜的判斷邏輯簡(jiǎn)化。

意圖:允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為

二、狀態(tài)模式的結(jié)構(gòu)

在該類(lèi)圖中,我們看到三個(gè)角色:

(1)Context: 環(huán)境類(lèi),定義客戶感興趣的接口,維護(hù)一個(gè)State子類(lèi)的實(shí)例,這個(gè)實(shí)例對(duì)應(yīng)的是對(duì)象當(dāng)前的狀態(tài)。

(2)State:抽象狀態(tài)類(lèi)或者狀態(tài)接口,定義一個(gè)或者一組行為接口,表示該狀態(tài)下的行為動(dòng)作。

(3)ConcreteState: 具體狀態(tài)類(lèi),實(shí)現(xiàn)State抽象類(lèi)中定義的接口方法,從而達(dá)到不同狀態(tài)下的不同行為。

三、狀態(tài)模式的使用場(chǎng)景

1.一個(gè)對(duì)象的行為取決于它的狀態(tài),并且它必須在運(yùn)行時(shí)刻根據(jù)狀態(tài)改變它的行為。

2.一個(gè)操作中含有龐大的多分支結(jié)構(gòu),并且這些分支決定于對(duì)象的狀態(tài)。

例子:我們?cè)谖⒉┥峡吹揭黄恼?,覺(jué)得還不錯(cuò),于是想評(píng)論或者轉(zhuǎn)發(fā),但如果用戶沒(méi)有登錄,這個(gè)時(shí)候就會(huì)先自動(dòng)跳轉(zhuǎn)到登錄注冊(cè)界面,如果已經(jīng)登錄,當(dāng)然就可以直接評(píng)論或者轉(zhuǎn)發(fā)了。這里我們可以看到,我們用戶的行為是由當(dāng)前是否登錄這個(gè)狀態(tài)來(lái)決定的,這就是典型的狀態(tài)模式情景。

當(dāng)然還包括很多其他動(dòng)作,例如轉(zhuǎn)發(fā)、分享、打賞等等,都要重復(fù)判斷狀態(tài)才行,如果程序隨著需求的改動(dòng)或者功能邏輯的增加需要修改代碼,那么你只要遺漏了一個(gè)判斷,就會(huì)出問(wèn)題。

而使用狀態(tài)模式,可以很好地避免過(guò)多的if–else –分支,狀態(tài)模式將每一個(gè)狀態(tài)分支放入一個(gè)獨(dú)立的類(lèi)中,每一個(gè)狀態(tài)對(duì)象都可以獨(dú)立存在,程序根據(jù)不同的狀態(tài)使用不同的狀態(tài)對(duì)象來(lái)實(shí)現(xiàn)功能。

四、狀態(tài)模式和策略模式對(duì)比

如果我們?cè)诰帉?xiě)代碼的時(shí)候,遇到大量的條件判斷的時(shí)候,可能會(huì)采用策略模式來(lái)優(yōu)化結(jié)構(gòu),因?yàn)檫@時(shí)涉及到策略的選擇,但有時(shí)候仔細(xì)查看下,就會(huì)發(fā)現(xiàn),這些所謂的策略其實(shí)是對(duì)象的不同狀態(tài),更加明顯的是,對(duì)象的某種狀態(tài)也成為判斷的條件。

策略模式的Context含有一個(gè)Strategy的引用,將自身的功能委托給Strategy來(lái)完成。

我們把Strategy接口改個(gè)名字為State,這就是狀態(tài)模式了,同樣Context也有一個(gè)State類(lèi)型的引用,也將自己的部門(mén)功能委托給State來(lái)完成。

要使用狀態(tài)模式,我們必須明確兩個(gè)東西:狀態(tài)和每個(gè)狀態(tài)下執(zhí)行的動(dòng)作。

在狀態(tài)模式中,因?yàn)樗械臓顟B(tài)都要執(zhí)行相應(yīng)的動(dòng)作,所以我們可以考慮將狀態(tài)抽象出來(lái)。

狀態(tài)的抽象一般有兩種形式:接口和抽象類(lèi)。如果所有的狀態(tài)都有共同的數(shù)據(jù)域,可以使用抽象類(lèi),但如果只是單純的執(zhí)行動(dòng)作,就可以使用接口。

他們之間真正的區(qū)別在策略模式對(duì)Strategy的具體實(shí)現(xiàn)類(lèi)有絕對(duì)的控制權(quán),即Context要感知Strategy具體類(lèi)型。而狀態(tài)模式,Context不感知State的具體實(shí)現(xiàn),Context只需調(diào)用自己的方法,這個(gè)調(diào)用的方法會(huì)委托給State來(lái)完成,State會(huì)在相應(yīng)的方法調(diào)用時(shí),自動(dòng)為Context設(shè)置狀態(tài),而這個(gè)過(guò)程對(duì)Context來(lái)說(shuō)是透明的,不被感知的。

五、狀態(tài)模式的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1、封裝了轉(zhuǎn)換規(guī)則。

2、枚舉可能的狀態(tài),在枚舉狀態(tài)之前需要確定狀態(tài)種類(lèi)。

3、將所有與某個(gè)狀態(tài)有關(guān)的行為放到一個(gè)類(lèi)中,并且可以方便地增加新的狀態(tài),只需要改變對(duì)象狀態(tài)即可改變對(duì)象的行為。

4、允許狀態(tài)轉(zhuǎn)換邏輯與狀態(tài)對(duì)象合成一體,而不是某一個(gè)巨大的條件語(yǔ)句塊。

5、可以讓多個(gè)環(huán)境對(duì)象共享一個(gè)狀態(tài)對(duì)象,從而減少系統(tǒng)中對(duì)象的個(gè)數(shù)。

缺點(diǎn):

1、狀態(tài)模式的使用必然會(huì)增加系統(tǒng)類(lèi)和對(duì)象的個(gè)數(shù)。

2、狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜,如果使用不當(dāng)將導(dǎo)致程序結(jié)構(gòu)和代碼的混亂。

3、狀態(tài)模式對(duì)“開(kāi)閉原則”的支持并不太好,對(duì)于可以切換狀態(tài)的狀態(tài)模式,增加新的狀態(tài)類(lèi)需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源代碼,否則無(wú)法切換到新增狀態(tài);而且修改某個(gè)狀態(tài)類(lèi)的行為也需修改對(duì)應(yīng)類(lèi)的源代碼。

六、狀態(tài)模式的實(shí)現(xiàn)

抽象狀態(tài)類(lèi),定義一個(gè)接口以封裝與Context類(lèi)(Work)的一個(gè)特定狀態(tài)相關(guān)的行為。

public abstract class State
{
    public abstract void WriteProgram(Work w);
}

工作狀態(tài)類(lèi),每一個(gè)子類(lèi)實(shí)現(xiàn)一個(gè)與Context類(lèi)(Work)的一個(gè)狀態(tài)相關(guān)的行為。

//上午工作狀態(tài)
public class ForeNoonState : State
{
    public override void WriteProgram(Work w)
    {
        if (w.Hour < 12)
        {
            Console.WriteLine("當(dāng)前時(shí)間:{0}點(diǎn),上午工作,精神百倍", w.Hour);
        }
        else
        {
            //超過(guò)12點(diǎn),則轉(zhuǎn)入中午工作狀態(tài)
            w.SetState(new NoonState());
            w.WriteProgram();
        }
    }
}
//中午工作狀態(tài)
public class NoonState : State
{
    public override void WriteProgram(Work w)
    {
        if (w.Hour < 13)
        {
            Console.WriteLine("當(dāng)前時(shí)間:{0}點(diǎn),吃午飯,午休", w.Hour);
        }
        else
        {
            //超過(guò)13點(diǎn),則轉(zhuǎn)入下午工作狀態(tài)
            w.SetState(new AfterNoonState());
            w.WriteProgram();
        }
    }
}
//下午工作狀態(tài)
public class AfterNoonState : State
{
    public override void WriteProgram(Work w)
    {
        if (w.Hour < 17)
        {
            Console.WriteLine("當(dāng)前時(shí)間:{0}點(diǎn),下午工作,繼續(xù)努力", w.Hour);
        }
        else
        {
            //超過(guò)17點(diǎn),則轉(zhuǎn)入晚上工作狀態(tài)
            w.SetState(new EveningState());
            w.WriteProgram();
        }
    }
}
//晚上工作狀態(tài)
public class EveningState : State
{
    public override void WriteProgram(Work w)
    {
        if (w.Finish)
        {
            //如果狀態(tài)已完成,則轉(zhuǎn)入下班狀態(tài)
            w.SetState(new RestState());
            w.WriteProgram();
        }
        else
        {
            if (w.Hour < 21)
            {
                Console.WriteLine("當(dāng)前時(shí)間:{0}點(diǎn),加班", w.Hour);
            }
            else
            {
                //超過(guò)21點(diǎn),則轉(zhuǎn)入睡眠工作狀態(tài)
                w.SetState(new SleepingState());
                w.WriteProgram();
            }
        }
    }
}
//睡眠工作狀態(tài)
public class SleepingState : State
{
    public override void WriteProgram(Work w)
    {
        Console.WriteLine("當(dāng)前時(shí)間:{0}點(diǎn),睡覺(jué)", w.Hour);
    }
}
//下班休息狀態(tài)
public class RestState : State
{
    public override void WriteProgram(Work w)
    {
        Console.WriteLine("當(dāng)前時(shí)間:{0}點(diǎn),下班", w.Hour);
    }
}

工作類(lèi),Context類(lèi),維護(hù)一個(gè)ConcreteState子類(lèi)(工作狀態(tài)類(lèi))的實(shí)例,這個(gè)實(shí)例定義當(dāng)前的狀態(tài)

public class Work
{
    private State current;
    public Work()
    {
        //工作初始化為上午工作狀態(tài)
        current = new ForeNoonState();
    }
    //“鐘點(diǎn)”屬性,狀態(tài)轉(zhuǎn)換的依據(jù)
    private double hour;
    public double Hour
    {
        get { return hour; }
        set { hour = value; }
    }
    //“任務(wù)完成”屬性,是否能下班的依據(jù)
    private bool finish = false;
    public bool Finish
    {
        get { return finish; }
        set { finish = value; }
    }
     public void SetState(State s)
    {
        current = s;
    }
     public void WriteProgram()
    {
        current.WriteProgram(this);
    }
}

客戶端代碼

class Program
{
    //客戶端代碼
    static void Main(string[] args)
    {
        Work w = new Work();
        w.Hour = 9;
        w.WriteProgram();
        w.Hour = 10;
        w.WriteProgram();
        w.Hour = 12;
        w.WriteProgram();
        w.Hour = 13;
        w.WriteProgram();
        w.Hour = 14;
        w.WriteProgram();
        w.Hour = 17;
         w.Finish = false;
        //w.Finish = true;
        w.WriteProgram();
        w.Hour = 19;
        w.WriteProgram();
        w.Hour = 22;
        w.WriteProgram();
         Console.Read();
    }
}

結(jié)果

當(dāng)前時(shí)間:9點(diǎn),上午工作,精神百倍
當(dāng)前時(shí)間:10點(diǎn),上午工作,精神百倍
當(dāng)前時(shí)間:12點(diǎn),吃午飯,午休
當(dāng)前時(shí)間:13點(diǎn),下午工作,繼續(xù)努力
當(dāng)前時(shí)間:14點(diǎn),下午工作,繼續(xù)努力
當(dāng)前時(shí)間:17點(diǎn),加班
當(dāng)前時(shí)間:19點(diǎn),加班
當(dāng)前時(shí)間:22點(diǎn),睡覺(jué)

七、總結(jié)

在對(duì)象的行動(dòng)取決于本身的狀態(tài)時(shí),可以適用于狀態(tài)模式,免去了過(guò)多的if–else判斷,這對(duì)于一些復(fù)雜的和繁瑣的判斷邏輯有很好的幫助。但是使用狀態(tài)模式,勢(shì)必會(huì)造成更多的接口和類(lèi),對(duì)于非常簡(jiǎn)單的狀態(tài)判斷,可以不使用。

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Java中Finally關(guān)鍵字

    Java中Finally關(guān)鍵字

    與其他語(yǔ)言的模型相比,finally 關(guān)鍵字是對(duì) Java 異常處理模型的最佳補(bǔ)充。接下來(lái)通過(guò)本文給大家介紹Java中Finally關(guān)鍵字及finally關(guān)鍵字的使用相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧
    2016-05-05
  • Java字符串String相關(guān)類(lèi)常用方法詳解

    Java字符串String相關(guān)類(lèi)常用方法詳解

    這篇文章主要介紹了Java中的字符串?dāng)?shù)據(jù)類(lèi)型,包括字符串的創(chuàng)建、拼接、比較和常用方法,還介紹了StringBuilder和StringJoiner類(lèi)的定義和使用,以及它們?cè)趦?nèi)存中的管理方式,需要的朋友可以參考下
    2025-02-02
  • Java?電話號(hào)碼的組合示例詳解

    Java?電話號(hào)碼的組合示例詳解

    這篇文章主要介紹了Java?電話號(hào)碼的組合,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • java編寫(xiě)創(chuàng)建數(shù)據(jù)庫(kù)和表的程序

    java編寫(xiě)創(chuàng)建數(shù)據(jù)庫(kù)和表的程序

    這篇文章主要為大家詳細(xì)介紹了java編寫(xiě)創(chuàng)建數(shù)據(jù)庫(kù)和表的程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(30)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(30)

    下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你
    2021-07-07
  • Java使用協(xié)同過(guò)濾算法的代碼示例

    Java使用協(xié)同過(guò)濾算法的代碼示例

    在Java中實(shí)現(xiàn)協(xié)同過(guò)濾算法通常需要一些步驟,包括加載用戶-項(xiàng)目評(píng)分?jǐn)?shù)據(jù)、計(jì)算相似度、生成推薦等,以下是一個(gè)簡(jiǎn)化的基于用戶的協(xié)同過(guò)濾算法的代碼示例,感興趣的小伙伴跟著小編一起來(lái)看看吧
    2024-06-06
  • Java中final、static關(guān)鍵字與方法的重寫(xiě)和繼承易錯(cuò)點(diǎn)整理

    Java中final、static關(guān)鍵字與方法的重寫(xiě)和繼承易錯(cuò)點(diǎn)整理

    這篇文章主要給大家介紹了關(guān)于Java中final、static關(guān)鍵字與方法的重寫(xiě)和繼承易錯(cuò)點(diǎn)的相關(guān)資料,在Java編程中final關(guān)鍵字用于限制方法或類(lèi)的進(jìn)一步修改,final方法不能被子類(lèi)重寫(xiě),而static方法不可被重寫(xiě),只能被遮蔽,需要的朋友可以參考下
    2024-10-10
  • springboot加載命令行參數(shù)ApplicationArguments的實(shí)現(xiàn)

    springboot加載命令行參數(shù)ApplicationArguments的實(shí)現(xiàn)

    本文主要介紹了springboot加載命令行參數(shù)ApplicationArguments的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • springboot項(xiàng)目如何防止XSS攻擊

    springboot項(xiàng)目如何防止XSS攻擊

    XSS攻擊全稱跨站腳本攻擊,是一種在web應(yīng)用中的計(jì)算機(jī)安全漏洞,允許惡意web用戶將代碼植入到提供給其它用戶使用的頁(yè)面中。本文介紹防止XSS攻擊的方法
    2021-06-06
  • Java 常量池的實(shí)例詳解

    Java 常量池的實(shí)例詳解

    這篇文章主要介紹了Java 常量池的實(shí)例詳解的相關(guān)資料,Java的常量池中包含了類(lèi)、接口、方法、字符串等一系列常量值,需要的朋友可以參考下
    2017-09-09

最新評(píng)論

禹城市| 响水县| 永嘉县| 定日县| 米脂县| 彭泽县| 仁化县| 闻喜县| 十堰市| 长治县| 乐安县| 济南市| 宿州市| 霍州市| 房山区| 耒阳市| 清水河县| 长宁区| 金昌市| 日照市| 金门县| 鸡泽县| 镇平县| 梁山县| 恩平市| 邵阳县| 类乌齐县| 韶关市| 博客| 岳普湖县| 达州市| 肥东县| 资中县| 鹤庆县| 开阳县| 香港 | 武强县| 长乐市| 将乐县| 肇东市| 兴业县|