自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

設計模式系列—狀態(tài)模式

開發(fā) 前端
本篇和大家一起來學習狀態(tài)模式相關內容。

 模式定義

對有狀態(tài)的對象,把復雜的“判斷邏輯”提取到不同的狀態(tài)對象中,允許狀態(tài)對象在其內部狀態(tài)發(fā)生改變時改變其行為。

狀態(tài)模式把受環(huán)境改變的對象行為包裝在不同的狀態(tài)對象里,其意圖是讓一個對象在其內部狀態(tài)改變的時候,其行為也隨之改變。現(xiàn)在我們來分析其基本結構和實現(xiàn)方法。

模板實現(xiàn)如下:

  1. package com.niuh.designpattern.state.v1; 
  2.  
  3. /** 
  4.  * <p> 
  5.  * 狀態(tài)模式 
  6.  * </p> 
  7.  */ 
  8. public class StatePattern { 
  9.  
  10.     public static void main(String[] args) { 
  11.         //創(chuàng)建環(huán)境   
  12.         Context context = new Context(); 
  13.         //處理請求 
  14.         context.Handle(); 
  15.         context.Handle(); 
  16.         context.Handle(); 
  17.         context.Handle(); 
  18.     } 
  19.  
  20. //抽象狀態(tài)類 
  21. abstract class State { 
  22.     public abstract void Handle(Context context); 
  23.  
  24. //具體狀態(tài)A類 
  25. class ConcreteStateA extends State { 
  26.     public void Handle(Context context) { 
  27.         System.out.println("當前狀態(tài)是 A."); 
  28.         context.setState(new ConcreteStateB()); 
  29.     } 
  30.  
  31. //具體狀態(tài)B類 
  32. class ConcreteStateB extends State { 
  33.     public void Handle(Context context) { 
  34.         System.out.println("當前狀態(tài)是 B."); 
  35.         context.setState(new ConcreteStateA()); 
  36.     } 
  37.  
  38. //環(huán)境類 
  39. class Context { 
  40.     private State state; 
  41.  
  42.     //定義環(huán)境類的初始狀態(tài) 
  43.     public Context() { 
  44.         this.state = new ConcreteStateA(); 
  45.     } 
  46.  
  47.     //設置新狀態(tài) 
  48.     public void setState(State state) { 
  49.         this.state = state; 
  50.     } 
  51.  
  52.     //讀取狀態(tài) 
  53.     public State getState() { 
  54.         return (state); 
  55.     } 
  56.  
  57.     //對請求做處理 
  58.     public void Handle() { 
  59.         state.Handle(this); 
  60.     } 

輸出結果如下:

  • 當前狀態(tài)是 A.
  • 當前狀態(tài)是 B.
  • 當前狀態(tài)是 A.
  • 當前狀態(tài)是 B.

解決的問題

對象的行為依賴于它的狀態(tài)(屬性),并且可以根據(jù)它的狀態(tài)改變而改變它的相關行為。

 

模式組成

實例說明

實例概況

用“狀態(tài)模式”設計一個多線程的狀態(tài)轉換程序。

 

分析:多線程存在 5 種狀態(tài),分別為新建狀態(tài)、就緒狀態(tài)、運行狀態(tài)、阻塞狀態(tài)和死亡狀態(tài),各個狀態(tài)當遇到相關方法調用或事件觸發(fā)時會轉換到其他狀態(tài),其狀態(tài)轉換規(guī)律如下所示:

現(xiàn)在先定義一個抽象狀態(tài)類(TheadState),然后為上圖的每個狀態(tài)設計一個具體狀態(tài)類,它們是新建狀態(tài)(New)、就緒狀態(tài)(Runnable )、運行狀態(tài)(Running)、阻塞狀態(tài)(Blocked)和死亡狀態(tài)(Dead),每個狀態(tài)中有觸發(fā)它們轉變狀態(tài)的方法,環(huán)境類(ThreadContext)中先生成一個初始狀態(tài)(New),并提供相關觸發(fā)方法,下圖所示是線程狀態(tài)轉換程序的結構圖:

使用步驟

 

步驟1:定義抽象狀態(tài)類:線程狀態(tài)

  1. abstract class ThreadState { 
  2.     //狀態(tài)名 
  3.     protected String stateName; 

步驟2: 定義具體的狀態(tài)類

  1. //具體狀態(tài)類:新建狀態(tài) 
  2. class New extends ThreadState { 
  3.     public New() { 
  4.         stateName = "新建狀態(tài)"
  5.         System.out.println("當前線程處于:新建狀態(tài)."); 
  6.     } 
  7.  
  8.     public void start(ThreadContext hj) { 
  9.         System.out.print("調用start()方法-->"); 
  10.         if (stateName.equals("新建狀態(tài)")) { 
  11.             hj.setState(new Runnable()); 
  12.         } else { 
  13.             System.out.println("當前線程不是新建狀態(tài),不能調用start()方法."); 
  14.         } 
  15.     } 
  16.  
  17. //具體狀態(tài)類:就緒狀態(tài) 
  18. class Runnable extends ThreadState { 
  19.     public Runnable() { 
  20.         stateName = "就緒狀態(tài)"
  21.         System.out.println("當前線程處于:就緒狀態(tài)."); 
  22.     } 
  23.  
  24.     public void getCPU(ThreadContext hj) { 
  25.         System.out.print("獲得CPU時間-->"); 
  26.         if (stateName.equals("就緒狀態(tài)")) { 
  27.             hj.setState(new Running()); 
  28.         } else { 
  29.             System.out.println("當前線程不是就緒狀態(tài),不能獲取CPU."); 
  30.         } 
  31.     } 
  32.  
  33. //具體狀態(tài)類:運行狀態(tài) 
  34. class Running extends ThreadState { 
  35.     public Running() { 
  36.         stateName = "運行狀態(tài)"
  37.         System.out.println("當前線程處于:運行狀態(tài)."); 
  38.     } 
  39.  
  40.     public void suspend(ThreadContext hj) { 
  41.         System.out.print("調用suspend()方法-->"); 
  42.         if (stateName.equals("運行狀態(tài)")) { 
  43.             hj.setState(new Blocked()); 
  44.         } else { 
  45.             System.out.println("當前線程不是運行狀態(tài),不能調用suspend()方法."); 
  46.         } 
  47.     } 
  48.  
  49.     public void stop(ThreadContext hj) { 
  50.         System.out.print("調用stop()方法-->"); 
  51.         if (stateName.equals("運行狀態(tài)")) { 
  52.             hj.setState(new Dead()); 
  53.         } else { 
  54.             System.out.println("當前線程不是運行狀態(tài),不能調用stop()方法."); 
  55.         } 
  56.     } 
  57.  
  58. //具體狀態(tài)類:阻塞狀態(tài) 
  59. class Blocked extends ThreadState { 
  60.     public Blocked() { 
  61.         stateName = "阻塞狀態(tài)"
  62.         System.out.println("當前線程處于:阻塞狀態(tài)."); 
  63.     } 
  64.  
  65.     public void resume(ThreadContext hj) { 
  66.         System.out.print("調用resume()方法-->"); 
  67.         if (stateName.equals("阻塞狀態(tài)")) { 
  68.             hj.setState(new Runnable()); 
  69.         } else { 
  70.             System.out.println("當前線程不是阻塞狀態(tài),不能調用resume()方法."); 
  71.         } 
  72.     } 
  73.  
  74. //具體狀態(tài)類:死亡狀態(tài) 
  75. class Dead extends ThreadState { 
  76.     public Dead() { 
  77.         stateName = "死亡狀態(tài)"
  78.         System.out.println("當前線程處于:死亡狀態(tài)."); 
  79.     } 

步驟3:定義環(huán)境類

  1. class ThreadContext { 
  2.     private ThreadState state; 
  3.  
  4.     ThreadContext() { 
  5.         state = new New(); 
  6.     } 
  7.  
  8.     public void setState(ThreadState state) { 
  9.         this.state = state; 
  10.     } 
  11.  
  12.     public ThreadState getState() { 
  13.         return state; 
  14.     } 
  15.  
  16.     public void start() { 
  17.         ((New) state).start(this); 
  18.     } 
  19.  
  20.     public void getCPU() { 
  21.         ((Runnable) state).getCPU(this); 
  22.     } 
  23.  
  24.     public void suspend() { 
  25.         ((Running) state).suspend(this); 
  26.     } 
  27.  
  28.     public void stop() { 
  29.         ((Running) state).stop(this); 
  30.     } 
  31.  
  32.     public void resume() { 
  33.         ((Blocked) state).resume(this); 
  34.     } 

輸出結果

  • 當前線程處于:新建狀態(tài).
  • 調用start()方法-->當前線程處于:就緒狀態(tài).
  • 獲得CPU時間-->當前線程處于:運行狀態(tài).
  • 調用suspend()方法-->當前線程處于:阻塞狀態(tài).
  • 調用resume()方法-->當前線程處于:就緒狀態(tài).
  • 獲得CPU時間-->當前線程處于:運行狀態(tài).
  • 調用stop()方法-->當前線程處于:死亡狀態(tài).

優(yōu)點

  1. 狀態(tài)模式將與特定狀態(tài)相關的行為局部化到一個狀態(tài)中,并且將不同狀態(tài)的行為分割開來,滿足“單一職責原則”。
  2. 減少對象間的相互依賴。將不同的狀態(tài)引入獨立的對象中會使得狀態(tài)轉換變得更加明確,且減少對象間的相互依賴。
  3. 有利于程序的擴展。通過定義新的子類很容易地增加新的狀態(tài)和轉換。

缺點

  1. 狀態(tài)模式的使用必然會增加系統(tǒng)的類與對象的個數(shù)。
  2. 狀態(tài)模式的結構與實現(xiàn)都較為復雜,如果使用不當會導致程序結構和代碼的混亂。

應用場景

通常在以下情況下可以考慮使用狀態(tài)模式。

  • 當一個對象的行為取決于它的狀態(tài),并且它必須在運行時根據(jù)狀態(tài)改變它的行為時,就可以考慮使用狀態(tài)模式。
  • 一個操作中含有龐大的分支結構,并且這些分支決定于對象的狀態(tài)時。

狀態(tài)模式的擴展

 

在有些情況下,可能有多個環(huán)境對象需要共享一組狀態(tài),這時需要引入享元模式,將這些具體狀態(tài)對象放在集合中供程序共享,其結構圖如下:

分析:共享狀態(tài)模式的不同之處是在環(huán)境類中增加了一個 HashMap 來保存相關狀態(tài),當需要某種狀態(tài)時可以從中獲取,其程序代碼如下:

  1. package com.niuh.designpattern.state.v3; 
  2.  
  3. import java.util.HashMap; 
  4.  
  5. /** 
  6.  * <p> 
  7.  * 共享狀態(tài)模式 
  8.  * </p> 
  9.  */ 
  10. public class FlyweightStatePattern { 
  11.     public static void main(String[] args) { 
  12.         //創(chuàng)建環(huán)境  
  13.         ShareContext context = new ShareContext(); 
  14.         //處理請求 
  15.         context.Handle(); 
  16.         context.Handle(); 
  17.         context.Handle(); 
  18.         context.Handle(); 
  19.     } 
  20.  
  21. //抽象狀態(tài)類 
  22. abstract class ShareState { 
  23.     public abstract void Handle(ShareContext context); 
  24.  
  25. //具體狀態(tài)1類 
  26. class ConcreteState1 extends ShareState { 
  27.     public void Handle(ShareContext context) { 
  28.         System.out.println("當前狀態(tài)是: 狀態(tài)1"); 
  29.         context.setState(context.getState("2")); 
  30.     } 
  31.  
  32. //具體狀態(tài)2類 
  33. class ConcreteState2 extends ShareState { 
  34.     public void Handle(ShareContext context) { 
  35.         System.out.println("當前狀態(tài)是: 狀態(tài)2"); 
  36.         context.setState(context.getState("1")); 
  37.     } 
  38.  
  39. //環(huán)境類 
  40. class ShareContext { 
  41.     private ShareState state; 
  42.     private HashMap<String, ShareState> stateSet = new HashMap<String, ShareState>(); 
  43.  
  44.     public ShareContext() { 
  45.         state = new ConcreteState1(); 
  46.         stateSet.put("1", state); 
  47.         state = new ConcreteState2(); 
  48.         stateSet.put("2", state); 
  49.         state = getState("1"); 
  50.     } 
  51.  
  52.     //設置新狀態(tài) 
  53.     public void setState(ShareState state) { 
  54.         this.state = state; 
  55.     } 
  56.  
  57.     //讀取狀態(tài) 
  58.     public ShareState getState(String key) { 
  59.         ShareState s = (ShareState) stateSet.get(key); 
  60.         return s; 
  61.     } 
  62.  
  63.     //對請求做處理 
  64.     public void Handle() { 
  65.         state.Handle(this); 
  66.     } 

輸出結果如下

  • 當前狀態(tài)是: 狀態(tài)1
  • 當前狀態(tài)是: 狀態(tài)2
  • 當前狀態(tài)是: 狀態(tài)1
  • 當前狀態(tài)是: 狀態(tài)2

 

源碼中的應用

  1. #JDK中的狀態(tài)模式: 
  2. java.util.Iterator 
  3. # 通過FacesServlet控制, 行為取決于當前JSF生命周期的階段(狀態(tài) 
  4. javax.faces.lifecycle.LifeCycle#execute() 

PS:以上代碼提交在 Github :

https://github.com/Niuh-Study/niuh-designpatterns.git

責任編輯:姜華 來源: 今日頭條
相關推薦

2020-10-23 09:40:26

設計模式

2020-11-03 13:05:18

命令模式

2022-01-12 13:33:25

工廠模式設計

2020-11-09 08:20:33

解釋器模式

2020-10-20 13:33:00

建造者模式

2020-11-05 09:38:07

中介者模式

2012-01-13 15:59:07

2021-10-26 00:21:19

設計模式建造者

2021-10-28 19:09:09

模式原型Java

2020-10-28 11:56:47

橋接模式

2021-06-09 08:53:34

設計模式策略模式工廠模式

2020-10-19 09:28:00

抽象工廠模式

2021-09-29 13:53:17

抽象工廠模式

2022-01-14 09:22:22

設計模式橋接

2013-11-26 15:48:53

Android設計模式SDK

2021-03-02 08:50:31

設計單例模式

2020-10-21 14:29:15

原型模式

2012-08-30 09:07:33

設計模式

2013-11-26 17:00:08

Android設計模式

2020-11-02 10:41:33

備忘錄模式
點贊
收藏

51CTO技術棧公眾號