【設計模式】享元模式 簡介 ( 定義 | 對象池 | 內部狀態 | 外部狀態 | 適用場景 | 相關角色 )
文章目錄
I . 享元模式 簡介
II . 享元模式 內部狀態 和 外部狀態
III . 享元模式 適用場景
IV . 享元模式 優缺點
V . 享元模式 相關模式
VI . 享元模式 相關角色
1 . 享元模式 簡介 :
享元模式的核心是
對象池 ,
使用對象時 , 先從對象池中獲取對象 ,
如果對象池中沒有 , 創建一個 , 放入對象池 , 然后再從對象池中獲取 ;
( 只能從對象池中拿對象 , 不能自己創建 )
① 設計模式類型 :
結構性 ;
② 享元模式 概念 :
通過減少創建對象數量 , 改善應用中使用對象的結構 , 使用
共享對象 ( 對象池中的對象 )
, 支持多個
細粒度對象 ( 使用時的大量對象 ) ;
③ 好處 :
減少創建對象的數量 , 從而減少內存的占用 , 提高性能 ;
2 . 細粒度對象 和 共享對象 :
目的是為了提高程序性能 ;
① 細粒度對象 :
是內存中的數量龐大的對象 ;
實際使用的數量龐大的對象 ;
② 共享對象 :
多個細粒度對象共享的部分數據 ;
對象緩存池中存儲的對象 ;
③ 舉例說明 :
使用字符串值 “abc” ,
首次使用 , 創建該字符串 , 將其放入字符串緩存池中 , 這個緩存池中的字符串就是
"共享對象" ,
應用中要大量使用 “abc” 字符串 , 比如使用 10 萬個 “abc” 字符串對象 , 這 10 萬個字符串對象就是
"細粒度對象" ,
此時肯定不會創建這么多對象 , 這 10 萬個對象使用時從字符串緩存池中查找緩存的那個
"共享對象"
即可 , 這樣節省了很大的內存開銷 ;
3 . 享元模式示例 :
Java 的 String 類型就是用了享元模式的設計模式 ;
① 定義字符串 : String str = "Hello" ;
② 內存中已有該字符串 :
如果之前已經有該字符串 , 就直接將字符串緩存池中的字符串返回 ,
③ 新字符串 :
如果內存中沒有該字符串 , 就創建一個新的字符串 , 放入緩存池中 ;
享元模式就是池技術 , 如字符串池 , 數據庫連接池 等 ;
使用對象時 , 先從池中查找 , 沒有找到再創建該對象 , 然后放入對象池中 ;
4 . 享元模式使用策略 :
用戶想要調用一個對象 , 去對象池中查找 , 如果對象池中有該對象 , 那么直接使用該對象 , 如果沒有 , 創建該對象 , 放入對象池中 , 然后再從對象池中獲取該對象 ;
對象對比 :
這里涉及到一個問題 , 如何確定對象池中的對象是不是用戶想要使用的對象呢 ?
5 . 引入 內部狀態 和 外部狀態 :
對象對比問題引出這兩個概念 , 對象中有很多數據 , 那么使用什么數據來確定兩個對象是否一致呢 , 這里使用 對象的 外部狀態 來確定 ;
① 內部狀態 :
對象的內部狀態不能作為對象對比的依據 , 所有對象的內部狀態都是一樣的數據 ;
② 外部狀態 :
對象的外部狀態每個都不一樣 , 每個對象都有一個唯一 外部狀態 值 , 類似于 身份證 , 哈希碼 這一類的信息 ;
③ 身份標識 :
在線程池中 , 使用外部狀態信息 , 唯一確定一個對象 , 作為對象的標識信息 ;
1 . 概念引入 :
區分這兩個概念的目的是為了維護享元模式的對象池 , 當用戶想要使用某個對象時 , 如何確定對象池中的對象是否是用戶想要調用的對象呢 , 這里就需要一些數據進行對比 , 數據一致 , 就說明是用戶想要的對象 , 數據不一致 , 就需要創建新對象 , 放入對象池 ;
① 內部狀態 :
有些數據所有的對象都一樣 , 顯然不能當做對象一致性對比的依據 , 這就是 內部狀態 ;
② 外部狀態 :
有些數據每個對象都不一樣 , 根據該數據確定對象的唯一性 , 相當于 哈希碼 , 身份證號 , 檔案編號 這一類的數據 , 這就是外部狀態 ;
內部狀態 和 外部狀態 本質是 信息數據
2 . 內部狀態 ( 共享信息 ) :
在享元模式中的對象中 , 不隨環境改變而改變的信息 ;
① 共享信息 :
內部狀態就是可以被共享的信息 ;
② 存儲位置 :
該信息存儲在享元對象內部 ;
③ 存儲形式 :
該信息作為對象的附加數據 , 不在具體的對象中存儲 , 可以被多個對象共享 ;
3 . 外部狀態 ( 不可共享信息 ) :
隨著外部環境改變 , 對象內部跟著改變 , 這部分內容就不能進行共享 ;
不可共享 :
外部狀態不可被共享 , 每個值都必須在不同的對象中維護 ;
1 . 享元模式 適用場景 :
① 底層開發 :
某個系統的底層開發 , 對性能要求比較高 , 可使用享元模式 ;
② 緩沖池 :
系統中實例對象數量龐大 , 需要緩沖池處理這些對象 ;
2 . 享元模式使用前提 :
系統中存在大量的對象 , 這些對象狀態大部分功能可以外部化 , 將這些功能抽離出來 , 只在內存中保留一份 ;
① 分離對象功能 :
系統中如果內存中持有大量對象 , 可能會溢出 , 將這些對象相同的部分分離出來 ;
② 用戶調用行為 :
如果有相同的業務請求 , 則優先使用內存中已有的對象進行處理 , 避免使用大量相同的對象 ;
③ 注意 :
這里只有在內存中有大量相同對象時 , 才考慮享元模式 , 如果內存中某類型的對象數量較少 , 沒有必要使用該模式 ;
1 . 享元模式 優點 :
① 降低內存占用 :
減少在內存中創建對象的數量 , 節省了內存 , 提高了效率 ;
② 減少創建對象開銷 :
創建對象時需要占用一定的開銷 , 如 new 操作 ; 可能構造函數中有訪問 文件 , 數據庫 , 網絡 等操作 , 也可以避免這些開銷 ;
2 . 享元模式 缺點 :
① 線程安全問題 :
在類中為了追求性能 , 一般使用的是 HashMap , ArrayList 等數據 , 這些數據結構都是線程不安全的 ; 使用 HashTable , Vector 線程安全了 , 但是性能會下降很多 ; 折中使用 ConcurrentHashMap 等 concurrent 包下的集合 ;
② 增加復雜性 :
將一個類拆解成多個類 , 系統復雜性肯定增加了 ;
1 . 享元模式 與 代理模式 :
代理模式需要代理某個類 , 生成該類需要花費較多的資源和時間 , 可以使用享元模式提高處理速度 ;
2 . 享元模式 與 單例模式 :
容器單例模式 , 復用對象 ;
1 . 抽象享元角色 :
抽象類 , 其中定義了 內部對象 , 外部對象 , 抽象行為 ;
① 內部對象 :
享元模式中 , 不關心該類數據 ;
② 外部對象 :
該值只能設置一次值 , 不能二次賦值 , 否則會造成對象池管理混亂 ; 一般要設置成 final 類型的 , 在構造函數中賦值 ;
③ 抽象行為 :
這是客戶調用的方法 ;
客戶使用享元模式時 , 創建的對象就是 抽象的享元角色 對象 , 調用的是抽象行為 ;
享元工廠管理時 , 也管理 抽象享元角色 對象 ;
2 . 具體享元角色 :
在構造函數中設置外部狀態 , 實現自己的業務邏輯 ;
3 . 享元工廠角色 :
在享元工廠中 , 維護對象池 , 當用戶調用 享元對象 時 , 從對象池中獲取該對象 , 如果沒有獲取到 , 那么創建新的 享元對象 , 放入對象池中 , 并返回該對象 ;
4 . 用戶調用 :
用戶聲明 抽象享元類對象 , 調用其定義的抽象行為 ;
任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。