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