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