文章目錄 概念概述 解決了什么 區別與聯系 享元模式的某個例子的細節分析
概念概述
ECS(Entity-Component-System) 1、Entity(實體):唯一標識符。 2、Component(組件):純數據容器(提一嘴UI實例,UI實例的引用可以作為數據放這里,system便可以使用)。 3、System(系統):負責邏輯處理。 享元模式(Flyweight Pattern) 1、核心思想:通過共享技術來高效地支持大量細粒度對象的復用。 2、它通過將對象的內在狀態(不變部分)和外在狀態(可變部分)分離,減少內存占用和對象創建開銷。 對象池(Object-Pool) 1、維護一組可復用的對象實例。 2、使用從池中取用完放回,避免頻繁創建和銷毀對象。
解決了什么
解耦與靈活性 性能優化 代碼可維護性 傳統面向對象繼承會導致復雜的類層次結構(如 Monster -> FlyingMonster -> BossMonster ) 數據連續性:同類型組件在內存中連續存儲,適合批量處理(如所有 PhysicsComponent 一起更新) 邏輯集中在 System 中,避免分散在多個類里 ECS 通過組合(Component)替代繼承,動態組裝實體行為(如給實體添加 FlyComponent 即可飛行) 多線程友好:不同 System 可以并行處理(如渲染和物理計算分離) 新增功能只需添加新組件和系統,無需修改現有代碼。
slfnte:ui&btl_uni_one_frm.
interface UIComponent { uiInstance : Laya. Sprite; isVisible : boolean;
}
復雜類設計關鍵區別說明
特性 容器類設計 ECS設計 實體表示 包含組件的對象 簡單的數字ID 組件訪問 character.health components.health.get(id) 系統處理 對象調用自己的方法 系統批量處理所有同類組件 內存布局 組件分散存儲 同類型組件連續存儲 添加組件 需要修改類定義 動態注冊到組件Map
內存消耗問題 對象創建性能問題 數據冗余問題 當需要創建大量相似對象時(如游戲中的樹木、子彈、NPC等),直接實例化會導致內存爆炸。 頻繁創建/銷毀對象會引發GC壓力(如JavaScript的垃圾回收) 多個對象包含重復數據(如相同紋理、模型) 享元方案:共享相同的內在狀態,僅存儲一份。 享元方案:通過對象池復用已有實例。 享元方案:將重復數據提取為共享部分
性能開銷問題 內存碎片問題 實時性要求 問題 頻繁實例化和銷毀對象(如子彈、敵人、粒子效果)會導致高CPU和內存開銷(尤其是構造函數復雜或GC壓力大的語言)。 反復分配/釋放內存可能引發內存碎片(尤其在C++等手動管理內存的語言中) 游戲或實時系統中,突發需求(如爆炸產生100顆爆炸碎片)可能導致瞬時卡頓。 解決 通過復用已有對象,減少 new/delete 或 instantiate/destroy 調用 對象池保持內存塊連續,提升內存訪問效率 預初始化對象池,確保快速響應。
區別與聯系
特性 享元模式 對象池 目標 共享不可變數據 復用可回收完整對象 適用場景 紋理、配置、模型等靜態資源/共同的邏輯函數 子彈、敵人等動態游戲對象 狀態管理 分離內在/外在狀態 對象完全一致,無狀態分離/對象需重置后復用
高頻復雜大量可復用對象=> ECS+對象池+享元模式 === [王炸]
享元模式的某個例子的細節分析
側重記錄這部分是因為思考是被享元模式引起的 享元模式與普通的繼承模式對比節省內存的例子之一分析如下:
場景:
需要100個精靈實例,每個精靈實例有n個屬性和3個函數 方式1:通過繼承模式組織類(有1個ExtCls1 方式2:通過享元模式+組合關系(有一個ExtCls2和一個享元類ThreeMthCls,ExtCls2引用了ThreeMthCls
對比依據(V8 需要為每個實例維護方法訪問路徑):
純繼承模式 繼承+引用享元類模式 指針 vs 方法副本 100 個 24 字節方法引用包裝 100 個 8 字節指針 實例創建 100個ExtCls1 100個ExtCls2 + 共同引用1個ThreeMthCls
說明:雖然繼承后創建的實例的函數時共享原型鏈上的,但是每個實例都要維護對應的方法訪問路徑(消耗38 * 100 =2400(B));分離后只需要共享1個內在狀態類即可(消耗1 8*100=800(B))