单例模式讲解
現在我們來學習單例模式,首先我們來看一下單例模式的定義和類型,他的定義是說,保證一個類僅有一個實例,并提供一個全局訪問的點,那這個定義還是非常簡單的,我們來看一下他的類型是創建型
那單例模式既簡單又復雜,尤其后面我們到coding的時候,會一起來演進咱們的單例模式,從中找到各種問題,及解決方案,同時會分析大量的原理,單例模式中的場景也很容易理解,想確保任何情況下都絕對只有一個實例,單例模式的實際應用也有很多,例如在單服務的情況下,網站的計數器可以用單例,在集群的模式下就要用共享的計數器了,還有一些應用配置,那用線程池的時候呢,一般也采用單例去設計,還有數據庫的連接池一般也是單例模式的,單例模式在我們日常工作中,使用的也是最廣泛的,所以我們認認真真的學會理解掌握這里面的基本原理,還是非常重要的
我們看一下單例模式的優點是什么呢,首先在內存里面只有一個實例,減少了內存開銷,特別是一個對象需要頻繁的創建,而且創建和銷毀的性能又無法優化,那這個時候單例的優勢就比較明顯了,可以避免對資源的多重占用,例如我們對一個文件進行寫操作,但由于只有一個實例,可以避免同時對同一個文件進行寫操作,那這個也容易理解,單例模式設置了全局訪問點,嚴格的控制訪問,也就是我對外呢不讓你new出來,你只能通過方法調用獲得,嚴格的控制訪問
單例的模式的缺點是什么呢,沒有接口,擴展會比較困難,如果想擴展的話,你要修改代碼,基本上沒有其它途徑可以實現
單例模式還有一些重點要講的,首先呢是私有構造器,這個是為了禁止從單例類外部調用構造函數,來創建這個對象,為了達到這個目的呢,必須設置構造函數的權限為private,這個呢很好理解,然后是線程安全,單例模式對于線程安全,非常重要,那在后面的coding中,也會一起來演進這個代碼,從線程安全這個角度來分析單例模式,那線程安全在單例模式中是非常非常重要的,這一點不能夠忽略,然后是延遲加載,延遲加載也是非常重要,我們想使用他的時候,再創建,那這個也是要延遲加載了,我們會一起來coding,各種方案以演進的方式來講解,關于延遲加載的一些解決方案,還有序列號和反序列化安全的問題,對于單例對象一旦序列號和反序列化的話,就會對單例進行破壞,那我們也會一起來分析源碼,debug跟進源碼,相信在這個過程中有所收獲的,還有一個重點就是反射,單例模式也要防止反射攻擊,雖然我們在日常寫代碼的時候,并不會特意這么做,但是基于工程師的思想,我們也要考慮這一點,并且也會領著一起來分析源碼,包括反射類包的一些源碼,還有如何防御反射攻擊,然后我們會一起分析來出坑,課程這么設計就是為了印象深刻,一塊來理解透,前三個點相信大家一定也知道,但是后兩個點,絕對是加分項,期望能夠理解透
后面也會重點來講一下單例模式,使用double check使用雙重鎖檢查鎖的內存機制,這里面有兩個圖,后面會重點講這兩個圖
還會講一下靜態內部類的解決方案,基于類初始化的延遲加載解決方案,這個圖等我們講到實現方案的時候,也會重點來講
非常重要的使用技能可以學習,例如說反編譯,我們使用JAD工具,對于枚舉類型進行反編譯,然后一起來分析代碼,具體反編譯如何使用呢,后面的coding也會一起來的,還有內存原理,就是前面說的那幾個圖,講這個主要是說,在單例模式實現方案的時候,對于線程安全這么一個關注點,是絕對不能忽略的,還有多線程debug,這個就更重要了,有講debug,我們演進TOMCAT集群,和Redis分布式的時候呢,我們要調試一個分布式鎖,那這個時候就需要多進程debug,那在我們這里,需要學習多線程debug,在實際的工作開發業務中,多線程這種場景,也是非常常見的,如果我們不能夠控制多線程中運行節奏的話,很有可能我們想重現一個問題,都重現不了,也無法找到問題的根源,所以這個技能是非常非常實用的,希望都能get這個技能
那我們看一下單例模式相關的設計模式,首先單例模式和工廠模式,那在一些業務場景中,我們可以把工廠類設計成單例模式的,這個就是屬于設計模式的一個結合,然后單例模式和享元模式,那享元模式我們后面也會講,也有一些業務場景,因為要管理很多單例對象,所以通過單例模式和享元模式和單例模式的一個結合,來完成單例模式的獲取,那這個結合場景下,享元模式的應用就類似于單例的一個工廠,只不過這個工廠,會拿出已經創建好的,并不會重新創建對象
在coding的過程中,希望我們的思維和技能呢,也是螺旋式上升的,那這個模式UML非常簡單,就不看UML了,然后一起來分析源碼,看一下單例模式的一些應用,現在我們一起來coding吧
?
總結
- 上一篇: 建造者模式源码解析(jdk-guava+
- 下一篇: 单列设计模式 懒汉式及多线程debug