本節書摘來異步社群《遊戲程式設計模式》一書中的第7章,第7.4節,作者: 【美】robert nystrom (尼斯卓姆) 譯者: 趙衛兵 , 許新星 , 姜召陽 , 陳侃 , 屈光輝 , 鄭炯彬 責編: 陳冀康,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
對于熟知面向對象方法的人來說,每一個條件分支都可以用動态分發來解決(換句話說,都可以用c++裡面的虛函數來解決)。但是,如果這樣做,你可能會把簡單問題複雜化。有時候,一個簡單的if語句就足夠了。
狀态模式的由來也有一些曆史原因。許多面向對象設計的擁護者—— gof和重構的作者martin fowler都是smalltalk出身。在那裡,如果有一個ifthen語句,我們便可以用一個表示true和false的對象來操作。
但是,在我們這個例子當中,我們發現面對對象設計也就是狀态模式更合适。
gof描述的狀态模式在應用到我們的例子中時如下。
首先,我們為狀态定義一個接口。每一個與狀态相關的行為都定義成虛函數。在我們的例子中,就是handleinput()和update()函數。
對于每一個狀态,我們定義了一個類并繼承此狀态接口。它的方法定義主角對應此狀态的行為。換句話說,把之前的switch語句裡面的每一個case語句裡的内容放置到它們對應的狀态類裡面去。比如:
注意,我們這裡chargetime_從heroine類中移到了duckingstate(躲避狀态)類中。這樣非常好,因為這個變量隻是對躲避狀态有意義,現在把它定義在這裡,正好顯式地反映了我們的對象模型。
接下來,我們在主角類中定義一個指針變量,讓它指向目前的狀态。我們把之前那個很大的switch語句去掉,并讓它去調用狀态接口的虛函數,最終這些虛方法就會動态地調用具體子狀态的相應函數。
狀态委托看起來很像政策模式和類型對象模式(第13章)。在這三個模式中,你會有一個主對象委托給另外的附屬對象。它們三者的差別主要在于目的不同:
政策模式的目标是将主類與它的部分行為進行解耦。
類型對象模式的目标是使得多個對象通過共享相同類型對象的引用來表現出相似性。
狀态模式的目标是通過改變主對象代理的對象來改變主對象的行為。
為了修改狀态,我們需要把state_指針指向另一個不同的heroinestate狀态對象。至此,我們的狀态模式就講完了。