最近學習到設計模式,現總結個人學習狀態模式內容【重點在於根據它的狀態改變而改變它的相關行爲】。
上一篇: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();
}
}
狀態模式與命令模式
命令模式的接口中只有一個方法。
狀態模式的接口中可以有多個方法。而且,狀態模式的實現類的方法,一般返回值,或者是改變實例變量的值。也就是說,**狀態模式一般和對象的狀態有關。**對象的行爲依賴於它的狀態(屬性),並且可以根據它的狀態改變而改變它的相關行爲。
以上僅爲個人學習,如果錯誤望指出,謝謝。