摘要:兩者都基于保持構(gòu)造函數(shù)私有并導(dǎo)出公共靜態(tài)成員以提供對唯一實(shí)例的訪問。在一種方法中,該成員是字段私有構(gòu)造器只調(diào)用一次,用來初始化靜態(tài)變量。由于缺少或者屬性的構(gòu)造器,這就保證了的全局一致性一旦類被實(shí)例化,只會存在一個實(shí)例,不多也不少。
??Singleton指僅僅被實(shí)例化一次的類 [Gamma95]。Singleton通常代表無狀態(tài)的對象,例如函數(shù)(第24項(xiàng))或者本質(zhì)上唯一的系統(tǒng)組件。使類稱為Singleton會使它的客戶端測試變得十分困難,因?yàn)槌撬鼘?shí)現(xiàn)了作為其類型的接口,否則不可能將模擬實(shí)現(xiàn)替換為單例。
??實(shí)現(xiàn)單例的方法有兩種。 兩者都基于保持構(gòu)造函數(shù)私有并導(dǎo)出公共靜態(tài)成員以提供對唯一實(shí)例的訪問。 在一種方法中,該成員是final字段:
// Singleton with public final field public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public void leaveTheBuilding() { ... } }
??私有構(gòu)造器只調(diào)用一次,用來初始化靜態(tài)變量Elvis.INSTANCE。由于缺少public或者protect屬性的構(gòu)造器,這就保證了Elvis的全局一致性:一旦Evlis類被實(shí)例化,只會存在一個Elvis實(shí)例,不多也不少。客戶端所做的任何事情都無法改變這一點(diǎn),但有一點(diǎn)需要注意:享有特權(quán)的客戶端可以借助AccessibleObject.setAccessible方法反射性地調(diào)用私有構(gòu)造函數(shù)(第65項(xiàng))。 如果你需要防御此攻擊,請修改構(gòu)造函數(shù)以使其在要求創(chuàng)建第二個實(shí)例時拋出異常。
??在實(shí)現(xiàn)Singleton的第二種方法中,公有的成員是個靜態(tài)工廠方法:
// Singleton with static factory public class Elvis { private static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public static Elvis getInstance() { return INSTANCE; } public void leaveTheBuilding() { ... } }
??對于靜態(tài)方法Elvis.getInstance的所有調(diào)用,都會返回同一個對象引用,所以,永遠(yuǎn)不會創(chuàng)建其他的Elvis實(shí)例(上述提醒依然適用)。
??公有域方法的主要好處在于,組成類的成員的聲明很清楚地聲明了這個類是一個Singleton:公有的靜態(tài)域是final的,所以該域總是包含同一個對象的引用。第二個好處就是它更加簡單。
??工廠方法的優(yōu)勢之一在于,它提供了靈活性:在不改變其API的前提下,我們可以改變類是否應(yīng)該為Singleton的想法。工廠方法返回唯一實(shí)例,但是,它可以很容易被修改,比如改成每個調(diào)用該方法的線程返回一個唯一的實(shí)例。第二個優(yōu)點(diǎn)是,如果你的應(yīng)用需要,你可以編寫泛型單例工廠(第30項(xiàng))。使用靜態(tài)工廠的最后一個優(yōu)點(diǎn)是方法參考可以用作供應(yīng)商,例如Elvis::instance是供應(yīng)商
??為了使利用這其中一種方法實(shí)現(xiàn)的Singleton類編程可序列化的(第12章),僅僅在聲明中加上“implements Serializable”是不夠的。為了維護(hù)并保證Singleton,必須聲明所有實(shí)例域都是瞬時(transient)的,并提供一個readResolve方法(第89項(xiàng))。否則,每次反序列化時,都會創(chuàng)建一個新的實(shí)例,在我們的示例中,會導(dǎo)致“假冒的Elvis”。為了防止這種情況,要在Elvis類中加入下面這個readResolve方法:
// readResolve method to preserve singleton property private Object readResolve() { // Return the one true Elvis and let the garbage collector // take care of the Elvis impersonator. return INSTANCE; }
??實(shí)現(xiàn)Singleton還有第三種方法。只需要編寫一個包含單個元素的枚舉類型:
// Enum singleton - the preferred approach public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } }
??這種方法類似于公共領(lǐng)域方法,但它更簡潔,免費(fèi)提供序列化機(jī)制,并提供了對多個實(shí)例化的鐵定保證,即使面對復(fù)雜的序列化或反射攻擊。這種方法可能會有點(diǎn)不自然,但單元素枚舉類型通常是實(shí)現(xiàn)單例的最佳方法。請注意,如果你的單例必須擴(kuò)展Enum以外的超類,則不能使用此方法(盡管你可以聲明枚舉來實(shí)現(xiàn)接口)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/73904.html
摘要:一個類可以提供一個公共靜態(tài)工廠方法,它僅僅是一第項(xiàng)遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器靜態(tài)工廠和構(gòu)造器有個共同的局限性他們都不能很好地擴(kuò)展到大量的可選參數(shù)。 ??本章涉及創(chuàng)建和銷毀對象,包括何時以及如何創(chuàng)建它們,何時以及如何避免創(chuàng)建它們,如何確保它們被及時銷毀,以及如何管理在銷毀之前必須進(jìn)行的清理操作。 第1項(xiàng):用靜態(tài)工廠方法代替構(gòu)造器 ??類允許客戶端獲取實(shí)例的傳統(tǒng)方法是提供公共構(gòu)造...
摘要:推薦序前言致謝第一章引言第二章創(chuàng)建和銷毀對象第項(xiàng)用靜態(tài)工廠方法代替構(gòu)造器第項(xiàng)遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器第項(xiàng)用私有構(gòu)造器或者枚舉類型強(qiáng)化屬性第項(xiàng)通過私有構(gòu)造器強(qiáng)化不可實(shí)例化的能力第項(xiàng)優(yōu)先考慮依賴注入來引用資源第項(xiàng)避免創(chuàng)建不必要的對象 推薦序 前言 致謝 第一章 引言 第二章 創(chuàng)建和銷毀對象 第1項(xiàng):用靜態(tài)工廠方法代替構(gòu)造器 第2項(xiàng):遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器 第...
摘要:本章中的大部分內(nèi)容適用于構(gòu)造函數(shù)和方法。第項(xiàng)其他方法優(yōu)先于序列化第項(xiàng)謹(jǐn)慎地實(shí)現(xiàn)接口第項(xiàng)考慮使用自定義的序列化形式第項(xiàng)保護(hù)性地編寫方法第項(xiàng)對于實(shí)例控制,枚舉類型優(yōu)先于第項(xiàng)考慮用序列化代理代替序列化實(shí)例附錄與第版中項(xiàng)目的對應(yīng)關(guān)系參考文獻(xiàn) effective-java-third-edition 介紹 Effective Java 第三版全文翻譯,純屬個人業(yè)余翻譯,不合理的地方,望指正,感激...
摘要:第二章創(chuàng)建和銷毀對象何時以及如何創(chuàng)建對象,何時以及如何避免創(chuàng)建對象,如何確保他們能夠適時地銷毀,以及如何管理對象銷毀之前必須進(jìn)行的各種清理動作。表示工廠方法所返回的對象類型。 第二章 創(chuàng)建和銷毀對象 何時以及如何創(chuàng)建對象,何時以及如何避免創(chuàng)建對象,如何確保他們能夠適時地銷毀,以及如何管理對象銷毀之前必須進(jìn)行的各種清理動作。 1 考慮用靜態(tài)工廠方法代替構(gòu)造器 一般在某處獲取一個類的實(shí)例最...
閱讀 2384·2021-11-24 09:38
閱讀 3428·2021-11-22 14:44
閱讀 1218·2021-07-29 13:48
閱讀 2683·2019-08-29 13:20
閱讀 1176·2019-08-29 11:08
閱讀 2150·2019-08-26 10:58
閱讀 1318·2019-08-26 10:55
閱讀 3213·2019-08-26 10:39