java設計模式_狀態模式

最近學習到設計模式,現總結個人學習狀態模式內容【重點在於根據它的狀態改變而改變它的相關行爲】。
上一篇:Java設計模式-責任鏈模式
設計模式彙總:https://blog.csdn.net/ljcc122/article/details/104789669

定義

對有狀態的對象,把複雜的“判斷邏輯”提取到不同的狀態對象中,允許狀態對象在其內部狀態發生改變時改變其行爲。

優缺點

優點

  • 允許對象在內部狀態發生改變時改變它的行爲,對象看起來好像修改了它的類。
  • 狀態模式將與特定狀態相關的行爲局部化到一個狀態中,並且將不同狀態的行爲分割開來,滿足“單一職責原則”。
  • 減少對象間的相互依賴。將不同的狀態引入獨立的對象中會使得狀態轉換變得更加明確,且減少對象間的相互依賴。

缺點

  • 增加系統類和對象的個數。
  • 狀態模式的結構與實現都較爲複雜,如果使用不當將導致程序結構和代碼的混亂。
  • 狀態模式對"開閉原則"的支持並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的源代碼(context),否則無法切換到新增狀態,而且修改某個狀態類的行爲也需修改對應類的源代碼

實現

模擬線程:
在這裏插入圖片描述

狀態模式模擬線程流程
在這裏插入圖片描述
類圖:
在這裏插入圖片描述

環境類(context):裏面維護了一個具體狀態的實例(AntFarmContext)

抽象狀態類(state):定義一個接口,封裝一些特定的行爲(AntFarmState)

具體狀態類(concreteState):每個子類實現一個與context的一個狀態相關的行爲(New,Blocked, Runnable,Running,Dead)

狀態模式的實現類的方法,一般返回值,或者是改變實例變量的值。也就是說,狀態模式一般和對象的狀態有關。

代碼

代碼中用到的靜態變量類

class StaticVariables {
	public static final String NEW = "New";//新生
	public static final String RUNNABLE = "Runnable";//就緒
	public static final String RUNNING = "Running";//運行
	public static final String BLOCKED = "Blocked";//掛起
	public static final String DEAD = "Dead";//死亡
}

狀態抽象類,以及具體實現

//抽象狀態類:線程狀態
abstract class ThreadState{
    String stateName; //狀態名
}
//具體狀態類:新建狀態
class New extends ThreadState{
    public New(){       
        stateName=StaticVariables.NEW;
    }
    public void start(ThreadContext th){//調用開始方法進入就緒狀態
        System.out.println("線程處於:"+stateName+", \t調用start()方法-->進入"+StaticVariables.RUNNABLE+"狀態");
        if(StaticVariables.NEW.equals(stateName)) {
        	th.setState(new Runnable());
        } else {
            System.out.println("線程"+stateName+",不能調用start()方法.");
        }
    }   
}
//具體狀態類:就緒狀態
class Runnable extends ThreadState{
    public Runnable(){       
        stateName=StaticVariables.RUNNABLE;
    }
    public void getCPU(ThreadContext th){//獲取cpu時間進入運行狀態
        System.out.println("線程處於:"+stateName+",獲得CPU時間-->進入"+StaticVariables.RUNNING+"狀態");
        if(StaticVariables.RUNNABLE.equals(stateName)){
        	th.setState(new Running());
        } else {
            System.out.println("當前線程"+stateName+",不能獲取CPU.");
        }
    }   
}
//具體狀態類:運行狀態
class Running extends ThreadState{
    public Running(){       
        stateName=StaticVariables.RUNNING;
    }
    public void waits(ThreadContext th){//進入掛起狀態
        System.out.println("線程處於: "+stateName+",\t調用waits()方法-->進入"+StaticVariables.BLOCKED+"狀態");
        if(StaticVariables.RUNNING.equals(stateName)){
        	th.setState(new Blocked());
        }else {
            System.out.println("線程"+stateName+",不能調用waits()方法.");
        }
    }
    public void dead(ThreadContext th){//進入死亡狀態
        System.out.println("線程處於: "+stateName+",\t調用dead()方法-->進入"+StaticVariables.DEAD+"狀態");
        if(StaticVariables.RUNNING.equals(stateName)){
        	th.setState(new Dead());
        }else{
            System.out.println("線程"+stateName+",不能調用dead()方法.");
        }
    }
}
//具體狀態類:阻塞狀態
class Blocked extends ThreadState{
    public Blocked(){       
        stateName=StaticVariables.BLOCKED;
    }
    public void ready(ThreadContext th){//進入就緒狀態
        System.out.println("線程處於: "+stateName+",\t調用ready()方法-->進入"+StaticVariables.RUNNABLE+"狀態");
        if(StaticVariables.BLOCKED.equals(stateName)){    
        	th.setState(new Runnable());
        }else{
            System.out.println("線程"+stateName+",不能調用ready()方法.");
        }
    }   
}
//具體狀態類:死亡狀態
class Dead extends ThreadState{
    public Dead(){
        stateName=StaticVariables.DEAD;
        System.out.println("線程處於: "+stateName);   
    }   
}

上下文對象

//環境類
class ThreadContext{
    private ThreadState state;
    ThreadContext() { state=new New();//進入新生態
    }
    public void setState(ThreadState state) { this.state=state;}
    public ThreadState getState(){return state;}   
    public void start(){//開始->進入新生態
    	if(state instanceof New) {
    		((New) state).start(this);
    	} else{
    		System.out.println("當前狀態已爲"+state.stateName+",不可直接運行!");
    	}
    }//運行
    public void getCPU(){ //獲取cpu時間片->準備進入運行態
    	if(state instanceof Runnable) {
    		((Runnable) state).getCPU(this);
    	}else {
    		System.out.println("當前狀態已爲"+state.stateName+", 直接可以繼續運行!");
    	}
    }
    public void waits(){//進入等待狀態->掛起線程
    	if(state instanceof Running) {
        	((Running) state).waits(this);
    	} else {
    		System.out.println("當前狀態爲"+state.stateName+",不能轉入waits狀態");
    	}
    }
    public void dead(){//死亡方法->線程運行結束
    	if(state instanceof Running) {
    		((Running) state).dead(this);
    	} else  {
    		System.out.println("當前狀態爲"+state.stateName+",不能直接死亡狀態");

    	}
    }
    public void ready(){//掛起的線程->進入就緒狀態
    	if(state instanceof Blocked) {
        	((Blocked) state).ready(this);
    	} else {
    		System.out.println("當前狀態已爲"+state.stateName+",直接繼續運行即可!");
    	}
    }
}

測試

public class Test {
	public static void main(String[] args) {
		ThreadContext context=new ThreadContext();
        context.start();
        context.getCPU();
        context.waits();
        context.ready();
        context.getCPU();
        context.dead();
//        context.start();
	}
}

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述


狀態模式與命令模式
命令模式的接口中只有一個方法。
狀態模式的接口中可以有多個方法。而且,狀態模式的實現類的方法,一般返回值,或者是改變實例變量的值。也就是說,**狀態模式一般和對象的狀態有關。**對象的行爲依賴於它的狀態(屬性),並且可以根據它的狀態改變而改變它的相關行爲。

以上僅爲個人學習,如果錯誤望指出,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章