模式導讀:ide
世間全部一切皆在變與不變之中,不管是人仍是物,咱們都會有各類不一樣的狀態,這些狀態豐富了咱們的一切,這些狀態看起來彷佛將咱們變成了另外一個樣子,實際上咱們的本質卻並未改變,人的狀態各類各樣,就單單論運動方式咱們就會有散步,游泳,跳動等等。容許對象在內部狀態發生改變時改變它的行爲,對象看起來好像修改了它的類,這即是狀態模式。this
參考類圖:spa
核心:
用於解決系統中複雜對象的狀態轉換以及不一樣狀態下行爲的封裝問題。
結構:
Context環境類(Person):維護一個State對象,它是定義了當前的狀態。
State抽象狀態類(State):
ConcretState具體狀態類(SwimState,WalkState,JumpState):每個類封裝了一個狀態對應的行爲。code
代碼實現:對象
1.定義一個狀態接口blog
1 package com.etc.state; 2 //狀態接口 3 public interface State { 4 //定義抽象方法獲取狀態狀況 5 void condition(Person p); 6 }
2.具體的狀態類接口
1 package com.etc.state; 2 //正常行走狀態 3 public class WalkState implements State { 4 5 @Override 6 public void condition(Person p) { 7 System.out.println(p.getName()+"正在公園散步。"); 8 try { 9 //正常行走狀態持續5000ms 10 Thread.sleep(5000); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 } 15 }
1 package com.etc.state; 2 //游泳狀態 3 public class SwimState implements State{ 4 5 @Override 6 public void condition(Person p) { 7 System.out.println(p.getName()+"正在游泳池裏面游泳!"); 8 try { 9 //游泳狀態持續5000ms 10 Thread.sleep(5000); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 } 15 }
1 package com.etc.state; 2 //跳動狀態 3 public class JumpState implements State{ 4 5 @Override 6 public void condition(Person p) { 7 System.out.println(p.getName()+"正在運動場上跳高!"); 8 try { 9 //讓跳動狀態維持5000ms 10 Thread.sleep(5000); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 } 15 }
3.狀態持有者類,裏面包含狀態設置的方法get
1 package com.etc.state; 2 3 public class Person { 4 5 private String name; 6 //正常行走狀態 7 public static final State walk=new WalkState(); 8 //游泳狀態 9 public static final State swim=new SwimState(); 10 //跳動狀態 11 public static final State jump=new JumpState(); 12 //默認是正常行走 13 private State state=walk; 14 15 public String getName() { 16 return name; 17 } 18 public void setName(String name) { 19 this.name = name; 20 } 21 22 public Person(String name) { 23 super(); 24 this.name = name; 25 } 26 27 //獲取當前狀態 28 public void setState(State state) { 29 this.state=state; 30 state.condition(this); 31 } 32 33 }
4.客戶端it
1 package com.etc.state; 2 3 public class Client { 4 5 public static void main(String[] args) throws InterruptedException { 6 7 Person p=new Person("曹操"); 8 System.out.println("-------正常行走狀態-------"); 9 p.setState(p.walk); 10 System.out.println("-------游泳狀態-------"); 11 p.setState(p.swim); 12 System.out.println("-------跳動狀態-------"); 13 p.setState(p.jump); 14 } 15 }
效果截圖:io
狀態模式優缺點:
優勢:
一、封裝了轉換規則。
二、枚舉可能的狀態,在枚舉狀態以前須要肯定狀態種類。
三、將全部與某個狀態有關的行爲放到一個類中,而且能夠方便地增長新的狀態,只須要改變對象狀態便可改變對象的行爲。
四、容許狀態轉換邏輯與狀態對象合成一體,而不是某一個巨大的條件語句塊。
五、可讓多個環境對象共享一個狀態對象,從而減小系統中對象的個數。
缺點:
一、狀態模式的使用必然會增長系統類和對象的個數。
二、狀態模式的結構與實現都較爲複雜,若是使用不當將致使程序結構和代碼的混亂。
三、狀態模式對"開閉原則"的支持並不太好,對於能夠切換狀態的狀態模式,增長新的狀態類須要修改那些負責狀態轉換的源代碼,不然沒法切換到新增狀態,並且修改某個狀態類的行爲也需修改對應類的源代碼。
適用場景:
一、行爲隨狀態改變而改變的場景。 二、條件、分支語句的代替者。