前言 因為游戲開發在架構上要考慮性能和實際需求,在儘量不引入第三方庫、框架的前提下進行開發,所以在編碼時候會經常用到設計模式對代碼進行復用,對業務邏輯架構解耦,儘量減少hard code。 單例模式(Singleton Pattern) 單例模式經常會用在邏輯上唯一的對象(通常用於重量級資源)上,如 ...
前言
因為游戲開發在架構上要考慮性能和實際需求,在儘量不引入第三方庫、框架的前提下進行開發,所以在編碼時候會經常用到設計模式對代碼進行復用,對業務邏輯架構解耦,儘量減少hard code。
單例模式(Singleton Pattern)
單例模式經常會用在邏輯上唯一的對象(通常用於重量級資源)上,如Factory、Context、Resource、Pool和Service等,但在代碼細節上需要註意開放出去的介面以及該介面的嚴格語義。單例模式通常帶有生命周期函數,有利於結合框架自己的生命周期管理進行初始化或銷毀操作。在開發過程中會遇到一些不好的例子,如變數都是類靜態成員變數、方法都是靜態方法,這樣寫的代碼可能在調用上的結果符合“單例”這個語義,但是會讓其他人感到困惑。
工廠模式(Factory Pattern)
使用工廠模式來統一創建對象有利於管理對象的生命周期,通常會組合單例模式、代理模式、策略模式,對複雜的對象進行組裝,對創建的對象進行統一管理。統一對象入口的好處在開發初期可能不明顯,但隨著開發進度的推動,業務的越來越複雜,統一入口容易更好地跟蹤對象的生命周期,也容易的對某類對象初始化時進行統一的操作。
策略模式(Strategy Pattern)
對於一些邏輯相似但實現的細節不同粒度又比較細的業務,可以將保證語義粒度適中的介面提取出來,按不同的實現邏輯來封裝成不同的策略,在通過策略容器(通常是工廠容器)在上層業務中進行組合調用。這樣既可以保證邏輯結構的清晰又便於擴展。在游戲開發中,狀態機就是一個使用策略模式的例子,狀態機本身就是一個策略容器,它將與狀態相關的行為從大量的跳轉中抽離處理,讓代碼結構更清晰明瞭。代碼結構越清晰,跳轉越少意味著出現BUG機率越低,調試起來更容易。個人覺得策略模式的關註點應該在介面的粒度上,它跟代理模式不同,要求粒度適中,根據具體的業務去動態選擇策略使得封裝的代碼脫離於客戶代碼。使用策略模式來解耦代碼是一個很好的選擇。
代理模式(Proxy Pattern)
代理模式跟策略模式其實很相似,粒度比策略模式粗,用於控制訪問對象。舉個例子,有一個複雜的數據對象有一個通用的二進位序列化介面,因為業務擴大,序列化數據越來越大,而網路層限制了協議的最大長度。這時是需要改網路底層?把公共的序列化介面改掉?還是在調用的代碼上hard code一次裁剪後的序列化代碼?答案是顯而易見的:只需要一個面對這個協議的對象訪問器,而這個訪問器只需要根據業務實現裁剪後的序列化介面。使用代理模式,更好的保護對象的封裝,讓頻繁改變的業務跟穩定的對象隔離開來。
觀察者模式(Observer Pattern)/訂閱發佈模式(Subscribe/Publish)
這兩個模式主要為瞭解耦獨立對象間的耦合,在這裡放在一起來講,因為這兩個模式主要區別在結構上,觀察者模式是直接耦合的,發佈訂閱模式是鬆散耦合的。在游戲開發上中經常看到XXXListener,這就是用了這兩個模式(大多數用訂閱發佈模式)。在游戲開發中,除了框架提供的事件生命周期外,其實可以用這些模式去鬆散具體業務的耦合。舉個例子,在一個複雜的養成系統上有很多條養成線,養成線互相有勾連,養成線的變動除了系統與角色的交互操作外,其他的養成線的交互操作應該只停留在這個養成系統本身,這時候就需要觀察者模式/發佈訂閱模式將這些養成線的交互隔離開來。
模板模式(Template Pattern)
這個模式偏向於框架編程,在實際開發中需要考慮到common——domain的比重,在考慮實際需要的抽象程度和業務的粒度。抽象程度太高會導致開發效率降低和實現難度增大,抽象程度太低又會導致業務性太強以致不好擴展和維護,這是一個值得深思的問題。
組合模式(Composite Pattern)
面向對象最重要的復用方式多態和組合,組合模式將不穩定的對象隔離,以樹狀結構連接起來。使用組合模式的好處是頻繁改動的部分不會影響到穩定的整體,但缺點是不能使用多態這個語法糖來進行直接復用。在開發中嚴謹地使用組合模式和繼承會讓代碼結構清晰和更從容面對業務地變更。關註點在於變的部分,就像陰陽兩極一樣,在實際開發中怎麼用組合/繼承也是一個值得深思的問題。
後話
其實還有很多設計模式我沒有提到,因為我的實際開發場景很少遇到。我認為,設計模式是死的,而業務是活的。按照《Clean Architecture》中Bob大叔介紹的軟體設計原則,再結合實際加以運用,不斷地提煉代碼,相信你也會發現編碼的樂趣。本人拙見,謹在此拋磚引玉。