[设计模式][c++]状态切换模式
轉自:http://blog.csdn.net/yongh701/article/details/49154439
?
狀態模式也是設計模式的一種,這種設計模式思想不復雜,就是實現起來的代碼有點復雜。主要出現在類傳遞參數上,尤其是C++這種不能直接類間互相調用都語言,實現狀態模式更難,當然,一切設計模式都是為了更簡短的主函數。
狀態模式是當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類,主要解決的是當控制一個對象狀態轉換的條件表達式過于復雜時的情況。把狀態的判斷邏輯轉移到表示不同的一系列類當中,可以把復雜的邏輯判斷簡單化。主要有以下三種角色:
1、上下文環境(Context):它定義了客戶程序需要的接口并維護一個具體狀態角色的實例,將與狀態相關的操作委托給當前的Concrete State對象來處理。
2、抽象狀態(State):定義一個接口以封裝使用上下文環境的的一個特定狀態相關的行為。
3、具體狀態(Concrete State):實現抽象狀態定義的接口。
說是這樣的意思:
舉個例子來說明吧,如下圖:
現在要求再主函數中,直接一行代碼context->switch_state();從狀態A切到狀態B。
這里利用狀態模式來實現,具體狀態就是狀態A與狀態B,然后上下文存在一個“轉換狀態”的方法。之后狀態A與狀態B共同接口就是抽象狀態State。具體實現代碼如下:
?
[cpp]?view plaincopy print?
運行結果如下圖:
?
可以看到,在主函數中,只是初始化了上下文,然而不停調用上下文的switch_state()方法,卻在兩個具體狀態A與B之間跳轉。然而,同樣的一句switch_state()有著不同實現,打印的內容是不同。
上述代碼還有C++的特色,各個具體狀態中,所對應轉換狀態方法,只能在類外實現,而不能在直接在StateA與StateB里面實現。因為C++不像Java,Java編譯的時候一次性把所有東西讀進去。C++是見一行讀一行。這里Context類用到State,StateA與StateB用到了Context,類間相互調用在C++中是不行的。
同時,注意在上下文類Context的構造類,對各個具體狀態初始化,也就是注冊各個具體狀態到上下文,否則編譯是過了,卻在程序中出現空指針。
那么這種狀態模式到底有什么呢?這里用一道2011年下半年的軟件設計師軟考題目再來說明:
題目是這樣的:
某大型商場內安裝了多個簡易的紙巾售賣機,自動出售2元錢一包的紙巾,且每次僅售出一包紙巾,紙巾售賣機的狀態圖如圖5-1所示:
?
采用狀態(State)模式來實現該紙巾售賣機,得到如圖5-2所示的類圖,其中類State為抽象類,定義了投幣、退幣、出紙巾等方法接口。類SoldOutState、NoQuarterState、HasQuarterState、SoldState分別對應圖5-1紙巾售賣機的4種狀態。售出紙巾、紙巾售賣、買有投幣、有2元錢。
這里很顯然,如果不用狀態模式,會產生大量的if...else語句,代碼將很不容易改變,,難以拓展。狀態轉換隱藏在條件語句中,所以并不明顯未來加入的代碼可能導致bug。
那么用狀態模式,先來分析一下,這里具體狀態有4個,分別對應4個類,TissueMachine類就是開放給主函數的上下文,而用戶能夠操作的地方,有3個,一個是投幣、一個是退幣,另一個是按“出紙巾”,這是上下文TissueMachine能給主函數調用的方法就這三個。而沒有提到的售出方法dispense,是上下文自身內部的狀態裝換,因此只在售出紙巾這個狀態中實現這個方法。不過,由于抽象狀態State定義了這4個方法的接口,因此,4個具體狀態都要有這4個方法,當然具體實現因狀態不同而不同,具體代碼如下:
?
[cpp]?view plaincopy print?
運行結果如下:
?
這里設置紙巾機一開始僅有1個紙巾,分別做不同的測試,可見紙巾自動售貨機有不同的響應。
轉載于:https://www.cnblogs.com/lyggqm/p/7064565.html
總結
以上是生活随笔為你收集整理的[设计模式][c++]状态切换模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: go 数据类型和操作符
- 下一篇: MVC之排球比赛计分程序 ——(二)架构