單例:只能被實(shí)例化一次的類。用來表示那些本質(zhì)上唯一的系統(tǒng)組件。
單例的缺點(diǎn)
如果單例沒有實(shí)現(xiàn)接口途凫,則無(wú)法用模擬實(shí)現(xiàn)替換桐汤,所以很難測(cè)試單例類而克。
JDK5之前實(shí)現(xiàn)單例的兩種方法
都要把構(gòu)造函數(shù)私有化,并導(dǎo)出公有的靜態(tài)成員怔毛,以便允許客戶端能夠訪問該類的唯一實(shí)例员萍。
JDK5之前實(shí)現(xiàn)單例的兩種方法——公有域方法
第一種方法中,公有靜態(tài)成員是個(gè)final
域:
享有特權(quán)的客戶端可以借助
AccessibleObject.setAccessible
方法拣度,通過反射機(jī)制調(diào)用私有構(gòu)造函數(shù)碎绎。如果需要抵御這種攻擊,可以修改構(gòu)造函數(shù)抗果,讓它在被要求創(chuàng)建第二個(gè)實(shí)例的時(shí)候拋出異常筋帖。
JDK5之前實(shí)現(xiàn)單例的兩種方法——靜態(tài)工廠方法
第二種方法,公有的成員是個(gè)靜態(tài)工廠方法冤馏。
公有域方法與靜態(tài)工廠方法的對(duì)比
公有域方法的類成員的聲明很清楚地表明了這個(gè)類是一個(gè)單例:公有的靜態(tài)域都是final
日麸,所以該域?qū)⒖偸前嗤膶?duì)象引用。
公有域方法在性能上不再有任何優(yōu)勢(shì):現(xiàn)代的JVM幾乎都能夠?qū)㈧o態(tài)工廠方法的調(diào)用內(nèi)聯(lián)化逮光。
工廠方法的優(yōu)勢(shì):
靈活性——在不改變API的前提下代箭,可以改變?cè)擃悶榉菃卫9S方法可以返回該類的唯一實(shí)例涕刚,但是可以修改為每個(gè)線程返回一個(gè)唯一的實(shí)例嗡综。
與泛型相關(guān)。
公有域方法的優(yōu)勢(shì)
公有域方法比較簡(jiǎn)單副女。
JDK5之后實(shí)現(xiàn)單例的最好實(shí)踐——單例序列化
implements Serializable
必須聲明所有實(shí)例域都是瞬時(shí)的蛤高,并提供一個(gè)readResolve
方法蚣旱。否則每次反序列化時(shí)都會(huì)創(chuàng)建一個(gè)新的實(shí)例。
包含單個(gè)元素的枚舉類型
跟公有域方法類似戴陡,但是更簡(jiǎn)潔塞绿,并無(wú)償提供了序列化機(jī)制,絕對(duì)防止多次實(shí)例化恤批。
單元素的枚舉類型已經(jīng)成為實(shí)現(xiàn)單例的最佳方法异吻。