--- title: 'State 狀態 模式' disqus: kyleAlien --- State 狀態 模式 === ## Overview of Content 如有引用參考請詳註出處,感謝 :smile: > 當一個物件內部**改變狀態時,像是改變了整個類別** :::success * 如果喜歡讀更好看一點的網頁版本,可以到我新做的網站 [**DevTech Ascendancy Hub**](https://devtechascendancy.com/) 本篇文章對應的是 [**State 狀態模式 | 實現解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_state/) ::: [TOC] ## State 設計使用場景 1. **物件 ++行為取決於狀態時++**,也就是 **同樣的行為,在不同狀態下會有不一樣的實作** :::info * **行為受狀態約束時**,可以很好的使用這個設計 > **但建議狀態不要超過 5 個以上** ::: 2. 大量 `if/else` or `switch/case` 在判斷狀態,再透過狀態來決定行為時 ### State 定義 & UML 建模 * **State 定義** **一個物件內部狀態改變時**,**允許對相同行為有不同動作**,看起來像是改變了物件 * **State UML** 與 [**策略模式**](https://hackmd.io/XCp8xyAdQ5Wd5GTwphFB6A) 幾乎相同,但是 **++它不可相互取代++ 每種狀態都有特殊意義** | 類 | 功能 | | -------- | -------- | | `Context` | **環境角色,負責具體狀態的切換(商業邏輯)** | | `IState` | 共同行為的抽象宣告 | | `ConstateA、B` | **它有兩個責任**:具體行為的實作(當前狀態)、狀態切換的行為(過渡到令一個狀態) | >  :::success * `State` & `Stragety` 設計差異 ? 主要要概念上的差異,**State 每個實作都是 ++無法互相取代++,每個狀態之間有關係,並且每個狀態要過渡到個別不同狀態(當前 -> 下一個狀態)** ::: ### State 設計 - 優缺點 * **State 設計優點** * 保證 **狀態的擴充性** * 保證 可維護性(不會影響到之前的正常功能) :::success * 狀態模式 配合 建造者模式,可以起到一個很好的封裝作用 > 可以依照建造順序產生多種不同狀態 ::: * **State 設計缺點** * 狀態增加時必定會增加其子類 ## State 實現 ### 謂何要使用 State 設計? * 在實現 State 設計之前我們先來看看問題點在哪,為何我們要使用 State 設計 從下面的程式中可以看出,它把所有功能都集合在 `McuControl`,如果需要修改、新增狀態,就必須修改已經完成的 Function :::warning * 問題點 ? 新增狀態時,須手動修改已完成的類,並不符合開閉原則 ::: ```kotlin= class McuControl { enum class State { ON, OFF } private var curState = State.OFF fun setState(state: State) { if (state != curState) { curState = state } } fun start() { when (curState) { State.ON -> println("MCU already on.") State.OFF -> println("MCU turn on.") } } fun stop() { when (curState) { State.ON -> println("MCU turn off.") State.OFF -> println("MCU already off.") } } fun showLed() { when (curState) { State.ON -> println("Shiny ~ Shiny ~ Shiny ~.") State.OFF -> println("Turn on MCU first.") } } } ``` ### State 標準實現 1. **`IState` 類**:透過 `IControl` 類,宣告 **狀態的共同方法**,也就是 **所有狀態的行為** ```java= // IState.java public interface IControl { void start(); void stop(); void showLed(); } ``` 2. **`ConstateA、B` 類**:具體實現 `IControl` 類的細節,這裡有兩個重點,^1.^ 實現 MCU 個 On/Off 兩種狀態 **針對這兩種狀況作出不同反應**、^2.^ **透過環境角色切換狀態** > 狀態的切換(過渡)是狀態模式很重要的一件事情! ```java= // 開啟模式 class PowerOnMode(private val context: Context) : IControl { override fun start() { // 透過狀態角色 切換狀態 context.setContext(Context.State.POWER_ON) // do nothing } override fun stop() { // 透過狀態角色 切換狀態 context.setContext(Context.State.POWER_OFF) println("MCU turn off.") } override fun showLed() { println("Shiny ~ Shiny ~ Shiny ~.") } } // --------------------------------------------------------------- // 關閉模式 class PowerOffMode(private val context: Context) : IControl { override fun start() { // 透過狀態角色 切換狀態 context.setContext(Context.State.POWER_ON) println("MCU turn on.") } override fun stop() { // 透過狀態角色 切換狀態 context.setContext(Context.State.POWER_OFF) // do nothing } override fun showLed() { // do nothing } } ``` 3. **`Context` 類**:環境切換角色,**它擁有所有的狀態,並且也透過它來切換不同的狀態模式** :::warning * 這裡可以看到 Context 對外提供的方法與 `IControl` 提供的相同,那它可以實做 `IControl` 嗎? **建議不要**!這邊應該要考慮到 Context 其實可以不需要跟 `IControl` 有相同方法,它應該對外提供自身的方法,而這裡只是剛好相同而已 ::: ```kotlin= class Context { private val powerOn = PowerOnMode(this) private val powerOff = PowerOffMode(this) enum class State { POWER_ON, POWER_OFF } private var curContext: IControl? = null fun setContext(state: State) { curContext = when(state) { State.POWER_ON -> powerOn State.POWER_OFF -> powerOff } } fun start() { curContext?.start() } fun stop() { curContext?.stop() } fun showLed() { curContext?.showLed() } } ``` * User 使用:**透過替換抽象,來達成相同功能 (抽象),不同行為 (細節)** ```java= fun main() { val contextEnv = Context().apply { setContext(Context.State.POWER_OFF) } contextEnv.apply { start() showLed() stop() showLed() } } ``` **--實作結果--** >  ## 更多的物件導向設計 物件導向的設計基礎如下,如果是初學者或是不熟悉的各位,建議可以從這些基礎開始認識,打好基底才能走個更穩(在學習的時候也需要不斷回頭看)! :::info * [**設計建模 2 大概念- UML 分類、使用**](https://devtechascendancy.com/introduction-to-uml-and-diagrams/) * [**物件導向設計原則 – 6 大原則(一)**](https://devtechascendancy.com/object-oriented-design-principles_1/) * [**物件導向設計原則 – 6 大原則(二)**](https://devtechascendancy.com/object-oriented-design-principles_2/) ::: ### 創建模式 - Creation Patterns * [**創建模式 PK**](https://devtechascendancy.com/pk-design-patterns-factory-builder-best/) * **創建模式 - `Creation Patterns`**: 創建模式用於「**物件的創建**」,它關注於如何更靈活、更有效地創建對象。這些模式可以隱藏創建對象的細節,並提供創建對象的機制,例如單例模式、工廠模式… 等等,詳細解說請點擊以下連結 :::success * [**Singleton 單例模式 | 解說實現 | Android Framework Context Service**](https://devtechascendancy.com/object-oriented_design_singleton/) * [**Abstract Factory 設計模式 | 實現解說 | Android MediaPlayer**](https://devtechascendancy.com/object-oriented_design_abstract-factory/) * [**Factory 工廠方法模式 | 解說實現 | Java 集合設計**](https://devtechascendancy.com/object-oriented_design_factory_framework/) * [**Builder 建構者模式 | 實現與解說 | Android Framwrok Dialog 視窗**](https://devtechascendancy.com/object-oriented_design_builder_dialog/) * [**Clone 原型模式 | 解說實現 | Android Framework Intent**](https://devtechascendancy.com/object-oriented_design_clone_framework/) * [**Object Pool 設計模式 | 實現與解說 | 利用 JVM**](https://devtechascendancy.com/object-oriented_design_object-pool/) * [**Flyweight 享元模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_flyweight/) ::: ### 行為模式 - Behavioral Patterns * [**行為模式 PK**](https://devtechascendancy.com/pk-design-patterns-cmd-strat-state-obs-chain/) * **行為模式 - `Behavioral Patterns`**: 行為模式關注物件之間的「**通信**」和「**職責分配**」。它們描述了一系列對象如何協作,以完成特定任務。這些模式專注於改進物件之間的通信,從而提高系統的靈活性。例如,策略模式、觀察者模式… 等等,詳細解說請點擊以下連結 :::warning * [**Stragety 策略模式 | 解說實現 | Android Framework 動畫**](https://devtechascendancy.com/object-oriented_design_stragety_framework/) * [**Interpreter 解譯器模式 | 解說實現 | Android Framework PackageManagerService**](https://devtechascendancy.com/object-oriented_design_interpreter_framework/) * [**Chain 責任鏈模式 | 解說實現 | Android Framework View 事件傳遞**](https://devtechascendancy.com/object-oriented_design_chain_framework/) * [**State 狀態模式 | 實現解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_state/) * [**Specification 規格模式 | 解說實現 | Query 語句實做**](https://devtechascendancy.com/object-oriented_design_specification-query/) * [**Command 命令、Servant 雇工模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_command_servant/) * [**Memo 備忘錄模式 | 實現與解說 | Android Framwrok Activity 保存**](https://devtechascendancy.com/object-oriented_design_memo_framework/) * [**Visitor 設計模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_visitor_dispatch/) * [**Template 設計模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_template/) * [**Mediator 模式設計 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_programming_mediator/) * [**Composite 組合模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_programming_composite/) ::: ### 結構模式 - Structural Patterns * [**結構模式 PK**](https://devtechascendancy.com/pk-design-patterns-proxy-decorate-adapter/) * **結構模式 - `Structural Patterns`**: 結構模式專注於「物件之間的組成」,以形成更大的結構。這些模式可以幫助你確保當系統進行擴展或修改時,不會破壞其整體結構。例如,外觀模式、代理模式… 等等,詳細解說請點擊以下連結 :::danger * [**Bridge 橋接模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_bridge/) * [**Decorate 裝飾模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_decorate/) * [**Proxy 代理模式 | 解說實現 | 分析動態代理**](https://devtechascendancy.com/object-oriented_design_proxy_dynamic-proxy/) * [**Iterator 迭代設計 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_iterator/) * [**Facade 外觀、門面模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_facade/) * [**Adapter 設計模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_adapter/) ::: ## Appendix & FAQ :::info ::: ###### tags: `Java 設計模式` `基礎進階`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up