淺談遊戲開發中常見的設計模式

前言  

由於遊戲開發在架構上要考慮性能和實際需求,在儘可能不引入第三方庫、框架的前提下進行開發,因此在編碼時候會常常用到設計模式對代碼進行復用,對業務邏輯架構解耦,儘可能減小hard code。編程

單例模式(Singleton Pattern)

單例模式常常會用在邏輯上惟一的對象(一般用於重量級資源)上,如Factory、Context、Resource、Pool和Service等,但在代碼細節上須要注意開放出去的接口以及該接口的嚴格語義。單例模式一般帶有生命週期函數,有利於結合框架本身的生命週期管理進行初始化或銷燬操做。在開發過程當中會遇到一些很差的例子,如變量都是類靜態成員變量、方法都是靜態方法,這樣寫的代碼可能在調用上的結果符合「單例」這個語義,可是會讓其餘人感到困惑。設計模式

工廠模式(Factory Pattern)

使用工廠模式來統一建立對象有利於管理對象的生命週期,一般會組合單例模式、代理模式、策略模式,對複雜的對象進行組裝,對建立的對象進行統一管理。統一對象入口的好處在開發初期可能不明顯,但隨着開發進度的推進,業務的愈來愈複雜,統一入口容易更好地跟蹤對象的生命週期,也容易的對某類對象初始化時進行統一的操做。網絡

策略模式(Strategy Pattern)

對於一些邏輯類似但實現的細節不一樣粒度又比較細的業務,能夠將保證語義粒度適中的接口提取出來,按不一樣的實現邏輯來封裝成不一樣的策略,在經過策略容器(一般是工廠容器)在上層業務中進行組合調用。這樣既能夠保證邏輯結構的清晰又便於擴展。在遊戲開發中,狀態機就是一個使用策略模式的例子,狀態機自己就是一個策略容器,它將與狀態相關的行爲從大量的跳轉中抽離處理,讓代碼結構更清晰明瞭。代碼結構越清晰,跳轉越少意味着出現BUG機率越低,調試起來更容易。我的以爲策略模式的關注點應該在接口的粒度上,它跟代理模式不一樣,要求粒度適中,根據具體的業務去動態選擇策略使得封裝的代碼脫離於客戶代碼。使用策略模式來解耦代碼是一個很好的選擇。架構

代理模式(Proxy Pattern)

代理模式跟策略模式其實很類似,粒度比策略模式粗,用於控制訪問對象。舉個例子,有一個複雜的數據對象有一個通用的二進制序列化接口,由於業務擴大,序列化數據愈來愈大,而網絡層限制了協議的最大長度。這時是須要改網絡底層?把公共的序列化接口改掉?仍是在調用的代碼上hard code一次裁剪後的序列化代碼?答案是顯而易見的:只須要一個面對這個協議的對象訪問器,而這個訪問器只須要根據業務實現裁剪後的序列化接口。使用代理模式,更好的保護對象的封裝,讓頻繁改變的業務跟穩定的對象隔離開來。框架

觀察者模式(Observer Pattern)/訂閱發佈模式(Subscribe/Publish)

這兩個模式主要爲了解耦獨立對象間的耦合,在這裏放在一塊兒來說,由於這兩個模式主要區別在結構上,觀察者模式是直接耦合的,發佈訂閱模式是鬆散耦合的。在遊戲開發上中常常看到XXXListener,這就是用了這兩個模式(大多數用訂閱發佈模式)。在遊戲開發中,除了框架提供的事件生命週期外,其實能夠用這些模式去鬆散具體業務的耦合。舉個例子,在一個複雜的養成系統上有不少條養成線,養成線互相有勾連,養成線的變更除了系統與角色的交互操做外,其餘的養成線的交互操做應該只停留在這個養成系統自己,這時候就須要觀察者模式/發佈訂閱模式將這些養成線的交互隔離開來。dom

模板模式(Template Pattern)

這個模式偏向於框架編程,在實際開發中須要考慮到common——domain的比重,在考慮實際須要的抽象程度和業務的粒度。抽象程度過高會致使開發效率下降和實現難度增大,抽象程度過低又會致使業務性太強以至很差擴展和維護,這是一個值得深思的問題。函數

組合模式(Composite Pattern)

面向對象最重要的複用方式多態和組合,組合模式將不穩定的對象隔離,以樹狀結構鏈接起來。使用組合模式的好處是頻繁改動的部分不會影響到穩定的總體,但缺點是不能使用多態這個語法糖來進行直接複用。在開發中嚴謹地使用組合模式和繼承會讓代碼結構清晰和更從容面對業務地變動。關注點在於變的部分,就像陰陽兩極同樣,在實際開發中怎麼用組合/繼承也是一個值得深思的問題。性能

後話

其實還有不少設計模式我沒有提到,由於個人實際開發場景不多遇到。我認爲,設計模式是死的,而業務是活的。按照《Clean Architecture》中Bob大叔介紹的軟件設計原則,再結合實際加以運用,不斷地提煉代碼,相信你也會發現編碼的樂趣。本人拙見,謹在此拋磚引玉。編碼

相關文章
相關標籤/搜索