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

Java設(shè)計模式之狀態(tài)模式State Pattern詳解

 更新時間:2022年11月01日 13:39:09   作者:流煙默  
這篇文章主要介紹了Java設(shè)計模式之狀態(tài)模式State Pattern,狀態(tài)模式允許一個對象在其內(nèi)部狀態(tài)改變的時候改變其行為。這個對象看上去就像是改變了它的類一樣

概述

狀態(tài)模式允許對象在內(nèi)部狀態(tài)改變時改變它的行為,對象看起來好像修改了它的類。這個模式將狀態(tài)封裝成獨立的類,并將動作委托到 代表當(dāng)前狀態(tài)的對象,我們知道行為會隨著內(nèi)部狀態(tài)而改變。

一個對象“看起來好像修改了它的類”是什么意思呢?從客戶的視角來看:如果說你使用的對象能夠完全改變它的行為,那么你會覺得,這個對象實際上是從別的類實例化而來的。然而,實際上,你知道我們是在使用組合通過簡單引用不同的狀態(tài)對象來造成類改變的假象。

狀態(tài)模式它主要用來解決對象在多種狀態(tài)轉(zhuǎn)換時,需要對外輸出不同的行為的問題。狀態(tài)和行為是一一對應(yīng)的,狀態(tài)之間可以相互轉(zhuǎn)換。

UML類圖

  • Context是一個類,它可以擁有一些內(nèi)部狀態(tài)。
  • State接口定義了一個所有具體狀態(tài)的共同接口,任何狀態(tài)都實現(xiàn)這個相同的接口,這樣一來狀態(tài)之間可以互相替換。
  • 不管在什么時候,只要有人調(diào)用Context的request()方法,它就會被委托到狀態(tài)來處理。
  • ConcreteState處理來自Context的請求。每一個ConcreteState都提供了它自己對于請求的實現(xiàn)。所以,當(dāng)Context改變狀態(tài)時,行為也跟著改變。

狀態(tài)模式與策略模式

以狀態(tài)模式而言,我們將一群行為封裝在狀態(tài)對象中,context的行為隨時可委托到那些狀態(tài)對象中的一個。隨著時間的流逝,當(dāng)前狀態(tài)在狀態(tài)對象集合中游走改變,以反映出context內(nèi)部的狀態(tài),因此context的行為也會隨著改變。但是context的客戶對于狀態(tài)對象了解不多,甚至根本是渾然不覺。

而以策略模式而言,客戶通常主動指定Context所要組合的策略對象是哪一個?,F(xiàn)在,固然策略模式讓我們具有彈性,能夠在運行時改變策略,但對于某個context對象來說,通常都只有一個最適當(dāng)?shù)牟呗詫ο蟆?/p>

一般來說,我們把策略模式想成是除了繼承之外的一種彈性替代方案。如果你使用繼承定義了一個類的行為,你將被這個行為困住,甚至要修改它都很難。有了策略模式,你可以通過組合不同的對象來改變行為。

我們把狀態(tài)模式想成是不用在context中放置許多條件判斷的替代方案。通過將行為包裝進狀態(tài)對象中,你可以通過在context內(nèi)見到地改變狀態(tài)對象來改變context的行為。

誰決定狀態(tài)轉(zhuǎn)換的流向

Context或者ConcreteState都可以。

一般來講,當(dāng)狀態(tài)轉(zhuǎn)換是固定的時候,就適合放在Context中。然而,當(dāng)轉(zhuǎn)換是動態(tài)的時候,通常就會放在狀態(tài)類中。

將狀態(tài)放在狀態(tài)類中的缺點是:狀態(tài)類之間產(chǎn)生了依賴。

State是接口還是抽象類

答:都可以。如果我們沒有共同的功能可以放進抽象類中,就會使用接口。在你實現(xiàn)狀態(tài)模式時,很可能想使用抽象類。這么一來,當(dāng)你以后需要在抽象類中加入新的方法是就很容易,不需要打破具體狀態(tài)的實現(xiàn)。

應(yīng)用案例分析

請編寫程序完成APP 抽獎活動具體要求如下:

  • 假如每參加一次這個活動要扣除用戶50 積分,中獎概率是10%
  • 獎品數(shù)量固定,抽完就不能抽獎
  • 活動有四個狀態(tài): 可以抽獎、不能抽獎、發(fā)放獎品和獎品領(lǐng)完
  • 活動的四個狀態(tài)轉(zhuǎn)換關(guān)系圖

那么需要如何做呢?

  • 定義出一個接口(或抽象類)叫狀態(tài)接口,每個狀態(tài)都實現(xiàn)(繼承)它。
  • 接口有扣除積分方法、抽獎方法、發(fā)放獎品方法

狀態(tài)抽象類

/**
 * 狀態(tài)抽象類
 */
public abstract class State {
	// 扣除積分 - 50
    public abstract void deductMoney();
    // 是否抽中獎品
    public abstract boolean raffle();
    // 發(fā)放獎品
    public abstract  void dispensePrize();
}

可以抽獎的狀態(tài)

public class CanRaffleState extends State {
    RaffleActivity activity;
    public CanRaffleState(RaffleActivity activity) {
        this.activity = activity;
    }
    //已經(jīng)扣除了積分,不能再扣
    @Override
    public void deductMoney() {
        System.out.println("已經(jīng)扣取過了積分");
    }
    //可以抽獎, 抽完獎后,根據(jù)實際情況,改成新的狀態(tài)
    @Override
    public boolean raffle() {
        System.out.println("正在抽獎,請稍等!");
        Random r = new Random();
        int num = r.nextInt(10);
        // 10%中獎機會
        if(num == 0){
            // 改變活動狀態(tài)為發(fā)放獎品 context
            activity.setState(activity.getDispenseState());
            return true;
        }else{
            System.out.println("很遺憾沒有抽中獎品!");
            // 改變狀態(tài)為不能抽獎
            activity.setState(activity.getNoRafflleState());
            return false;
        }
    }
    // 不能發(fā)放獎品
    @Override
    public void dispensePrize() {
        System.out.println("沒中獎,不能發(fā)放獎品");
    }
}

獎品發(fā)放完畢狀態(tài)

/**
 * 獎品發(fā)放完畢狀態(tài)
 * 說明,當(dāng)我們activity 改變成 DispenseOutState, 抽獎活動結(jié)束
 */
public class DispenseOutState extends State {
	// 初始化時傳入活動引用
    RaffleActivity activity;

    public DispenseOutState(RaffleActivity activity) {
        this.activity = activity;
    }
    @Override
    public void deductMoney() {
        System.out.println("獎品發(fā)送完了,請下次再參加");
    }
    @Override
    public boolean raffle() {
        System.out.println("獎品發(fā)送完了,請下次再參加");
        return false;
    }
    @Override
    public void dispensePrize() {
        System.out.println("獎品發(fā)送完了,請下次再參加");
    }
}

發(fā)放獎品的狀態(tài)

public class DispenseState extends State {
	 // 初始化時傳入活動引用,發(fā)放獎品后改變其狀態(tài)
    RaffleActivity activity;
    public DispenseState(RaffleActivity activity) {
        this.activity = activity;
    }
    @Override
    public void deductMoney() {
        System.out.println("不能扣除積分");
    }
    @Override
    public boolean raffle() {
        System.out.println("不能抽獎");
        return false;
    }
    //發(fā)放獎品
    @Override
    public void dispensePrize() {
        if(activity.getCount() > 0){
            System.out.println("恭喜中獎了");
            // 改變狀態(tài)為不能抽獎
            activity.setState(activity.getNoRafflleState());
        }else{
            System.out.println("很遺憾,獎品發(fā)送完了");
            // 改變狀態(tài)為獎品發(fā)送完畢, 后面我們就不可以抽獎
            activity.setState(activity.getDispensOutState());
            //System.out.println("抽獎活動結(jié)束");
            //System.exit(0);
        }
    }
}

不能抽獎狀態(tài)

public class NoRaffleState extends State {
	 // 初始化時傳入活動引用,扣除積分后改變其狀態(tài)
    RaffleActivity activity;
    public NoRaffleState(RaffleActivity activity) {
        this.activity = activity;
    }
    // 當(dāng)前狀態(tài)可以扣積分 , 扣除后,將狀態(tài)設(shè)置成可以抽獎狀態(tài)
    @Override
    public void deductMoney() {
        System.out.println("扣除50積分成功,您可以抽獎了");
        activity.setState(activity.getCanRaffleState());
    }
    // 當(dāng)前狀態(tài)不能抽獎
    @Override
    public boolean raffle() {
        System.out.println("扣了積分才能抽獎喔!");
        return false;
    }
    // 當(dāng)前狀態(tài)不能發(fā)獎品
    @Override
    public void dispensePrize() {
        System.out.println("不能發(fā)放獎品");
    }
}

抽獎活動(Context)

public class RaffleActivity {
	// state 表示活動當(dāng)前的狀態(tài),是變化
    State state = null;
    // 獎品數(shù)量
    int count = 0;
    // 四個屬性,表示四種狀態(tài)
    State noRafflleState = new NoRaffleState(this);
    State canRaffleState = new CanRaffleState(this);
    State dispenseState =   new DispenseState(this);
    State dispensOutState = new DispenseOutState(this);
    //構(gòu)造器
    //1. 初始化當(dāng)前的狀態(tài)為 noRafflleState(即不能抽獎的狀態(tài))
    //2. 初始化獎品的數(shù)量 
    public RaffleActivity( int count) {
        this.state = getNoRafflleState();
        this.count = count;
    }
    //扣分, 調(diào)用當(dāng)前狀態(tài)的 deductMoney
    public void debuctMoney(){
        state.deductMoney();
    }
    //抽獎 
    public void raffle(){
    	// 如果當(dāng)前的狀態(tài)是抽獎成功
        if(state.raffle()){
        	//領(lǐng)取獎品
            state.dispensePrize();
        }
    }
    public State getState() {
        return state;
    }
    public void setState(State state) {
        this.state = state;
    }
    //這里請大家注意,每領(lǐng)取一次獎品,count--
    public int getCount() {
    	int curCount = count; 
    	count--;
        return curCount;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public State getNoRafflleState() {
        return noRafflleState;
    }
    public void setNoRafflleState(State noRafflleState) {
        this.noRafflleState = noRafflleState;
    }
    public State getCanRaffleState() {
        return canRaffleState;
    }
    public void setCanRaffleState(State canRaffleState) {
        this.canRaffleState = canRaffleState;
    }
    public State getDispenseState() {
        return dispenseState;
    }
    public void setDispenseState(State dispenseState) {
        this.dispenseState = dispenseState;
    }
    public State getDispensOutState() {
        return dispensOutState;
    }
    public void setDispensOutState(State dispensOutState) {
        this.dispensOutState = dispensOutState;
    }
}

測試狀態(tài)模式

public class ClientTest {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 創(chuàng)建活動對象,獎品有1個獎品
        RaffleActivity activity = new RaffleActivity(1);
        // 我們連續(xù)抽300次獎
        for (int i = 0; i < 30; i++) {
            System.out.println("--------第" + (i + 1) + "次抽獎----------");
            // 參加抽獎,第一步點擊扣除積分
            activity.debuctMoney();
            // 第二步抽獎
            activity.raffle();
        }
	}
}

UML類圖如下:

到此這篇關(guān)于Java設(shè)計模式之狀態(tài)模式State Pattern詳解的文章就介紹到這了,更多相關(guān)Java狀態(tài)模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot支持Crontab任務(wù)改造的方法

    Spring Boot支持Crontab任務(wù)改造的方法

    這篇文章主要介紹了Spring Boot支持Crontab任務(wù)改造的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • 使用Java實現(xiàn)簡單搭建內(nèi)網(wǎng)穿透

    使用Java實現(xiàn)簡單搭建內(nèi)網(wǎng)穿透

    內(nèi)網(wǎng)穿透是一種網(wǎng)絡(luò)技術(shù),適用于需要遠程訪問本地部署服務(wù)的場景,本文主要為大家介紹了如何使用Java實現(xiàn)簡單搭建內(nèi)網(wǎng)穿透,感興趣的可以了解下
    2024-02-02
  • java實現(xiàn)IP地址轉(zhuǎn)換

    java實現(xiàn)IP地址轉(zhuǎn)換

    這篇文章主要為大家詳細介紹了java實現(xiàn)IP地址轉(zhuǎn)換,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java設(shè)計模式之外觀模式示例詳解

    Java設(shè)計模式之外觀模式示例詳解

    外觀模式為多個復(fù)雜的子系統(tǒng),提供了一個一致的界面,使得調(diào)用端只和這個接口發(fā)生調(diào)用,而無須關(guān)系這個子系統(tǒng)內(nèi)部的細節(jié)。本文將通過示例詳細為大家講解一下外觀模式,需要的可以參考一下
    2022-03-03
  • Java中的對象和引用詳解

    Java中的對象和引用詳解

    這篇文章主要介紹了Java中的對象和引用詳解的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • 開源項目ERM模型轉(zhuǎn)jpa實體maven插件使用

    開源項目ERM模型轉(zhuǎn)jpa實體maven插件使用

    這篇文章主要為大家介紹了開源項目ERM模型轉(zhuǎn)jpa實體maven插件的使用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-03-03
  • Java算法之堆排序代碼示例

    Java算法之堆排序代碼示例

    這篇文章主要介紹了Java算法之堆排序代碼示例,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • 淺談Springboot之于Spring的優(yōu)勢

    淺談Springboot之于Spring的優(yōu)勢

    這篇文章主要介紹了淺談Springboot之于Spring的優(yōu)勢,簡述了在Java EE開發(fā)中遇到的問題,言簡意賅,需要的朋友可以參考下。
    2017-09-09
  • MyBatis 中 ${}和 #{}的正確使用方法(千萬不要亂用)

    MyBatis 中 ${}和 #{}的正確使用方法(千萬不要亂用)

    這篇文章主要介紹了MyBatis 中 ${}和 #{}的正確使用方法,本文給大家提到了MyBatis 中 ${}和 #{}的區(qū)別,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • 聊聊Controller中RequestMapping的作用

    聊聊Controller中RequestMapping的作用

    這篇文章主要介紹了Controller中RequestMapping的作用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評論

麻阳| 名山县| 东乡族自治县| 大埔区| 宣恩县| 武隆县| 基隆市| 平安县| 穆棱市| 柳州市| 虎林市| 临颍县| 武邑县| 湖南省| 岐山县| 永丰县| 巫溪县| 钟山县| 西乌| 鱼台县| 玉田县| 龙山县| 台北市| 沙田区| 昌江| 福泉市| 长顺县| 舞钢市| 林芝县| 阿图什市| 鹤岗市| 江西省| 南京市| 依兰县| 南和县| 徐州市| 延安市| 邯郸县| 武夷山市| 墨竹工卡县| 麻城市|