国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

第1項:考慮靜態(tài)工廠方法而不是構(gòu)造函數(shù)

趙連江 / 3237人閱讀

摘要:提供靜態(tài)工廠方法而不是公共構(gòu)造函數(shù)既有優(yōu)點也有缺點。它們不像構(gòu)造函數(shù)那樣在文檔中脫穎而出,因此很難弄清楚如何實例化提供靜態(tài)工廠方法而不是構(gòu)造函數(shù)的類。

??類允許客戶端獲取實例的傳統(tǒng)方法是提供公共構(gòu)造器。還有一種技術(shù)應(yīng)該是每個程序員的工具箱的一部分。一個類可以提供一個公共靜態(tài)工廠方法,它僅僅是一個返回類實例的靜態(tài)方法。下面是布爾(布爾型的盒裝原語類)的一個簡單示例。這個方法將一個布爾原始值轉(zhuǎn)換成布爾對象引用:

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

??注意: 靜態(tài)工廠方法與設(shè)計模式 [Gamma95] 的工廠方法模式不同,在這個Item中描述的靜態(tài)工廠方法并不等同于設(shè)計模式中的工廠方法模式。

??一個類可以為其客戶提供靜態(tài)工廠方法,而不是公共構(gòu)造函數(shù)。提供靜態(tài)工廠方法而不是公共構(gòu)造函數(shù)既有優(yōu)點也有缺點。

??靜態(tài)工廠方法的一個優(yōu)點是,它們是有名稱的,而構(gòu)造函數(shù)的名稱都是一樣的。 如果構(gòu)造函數(shù)的參數(shù)本身不能描述返回的對象,那么使用一個精心命名的靜態(tài)工廠更容易使用,并且生成的客戶端代碼更容易閱讀。例如BigInteger的一個構(gòu)造函數(shù):BigInteger(int, int, Random),這個構(gòu)造函數(shù)返回一個BigInteger有可能是一個質(zhì)數(shù),使用一個精心命名的靜態(tài)工廠方法會更容易描述該方法返回的BigInteger類型,比如BigInteger.probablePrime(這是在Java 4 中添加的)。

??一個類只能有一個帶有給定簽名的構(gòu)造函數(shù)。程序員可以通過提供兩個構(gòu)造函數(shù)來繞過這個限制,這些構(gòu)造函數(shù)的參數(shù)列表只在參數(shù)類型的順序上有所不同。這是個相當(dāng)壞的主意。這樣使用這個API的用戶永遠(yuǎn)無法記住應(yīng)該使用哪個構(gòu)造函數(shù),并且最終會調(diào)用錯誤的構(gòu)造函數(shù)。使用這些構(gòu)造函數(shù)的人在不閱讀的引用類文檔的情況下是不知道代碼是干什么的。

??因為構(gòu)造函數(shù)有名稱,所以就不會有這個限制,在一個類需要使用多個簽名、多個構(gòu)造函數(shù)的情況下,用靜態(tài)工廠方法代替構(gòu)造函數(shù),并仔細(xì)選擇方法的名稱就可以突出構(gòu)造函數(shù)之間的差異了。

??靜態(tài)工廠方法的第二個優(yōu)點是,與構(gòu)造函數(shù)不同,它們不需要在每次被調(diào)用時創(chuàng)建一個新對象。 這允許不可變類(第17項)使用預(yù)先構(gòu)造的實例,或者在構(gòu)建時緩存實例,并重復(fù)分發(fā)它們,以避免創(chuàng)建不必要的重復(fù)對象。Boolean.valueOf(boolean)方法使用了這種方式:它從不創(chuàng)建對象。這種技術(shù)類似于享元模式[Gamma95]。如果經(jīng)常請求等效對象,特別是當(dāng)它們的創(chuàng)建成本很高時,它可以極大地提高性能。

??靜態(tài)工廠方法從重復(fù)調(diào)用中返回相同的對象的能力允許類在任何時候保持對實例的嚴(yán)格控制。這樣做的類被認(rèn)為是實例控制的。編寫實例控制類的原因有幾個。實例控制允許一個類保證它是一個單例(第3項)或非實例化的(第4項),并且它允許一個不可值的類(第17項)來保證沒有兩個相等的實例存在:當(dāng)且僅當(dāng)a==b成立時,a.equals(b)返回true,這是享元模式 [Gamma95] 的基礎(chǔ),枚舉類型就提供了這種保證。

??靜態(tài)工廠方法的第三個優(yōu)點是,與構(gòu)造函數(shù)不同,它們可以的對象可以是返回類型的任何子類的實例對象。 這使在選擇返回的對象的類時具有很大的靈活性。

??這種靈活性的一個應(yīng)用是,API可以返回對象,同時又不會使對象的類編程公有的,以這種方式隱藏實現(xiàn)類會使API變得非常簡潔。這種技術(shù)適用于基于接口的框架(interface-based frameworks,見第20項),因為在這種框架中,接口為靜態(tài)工廠方法提供了自然返回類型。

??在Java 8 之前,接口不能有靜態(tài)方法。按照慣例,名為Type的接口的靜態(tài)工廠方法被放置在一個不可實例化的名為Types的配套類(noninstantiable companion class)(第4項)中。例如,Java Collections Framework有45個便利實現(xiàn),分別提供了不可修改的集合、同步集合等等。幾乎所有這些實現(xiàn)都通過靜態(tài)工廠方法在一個不可實例化的類(java.util.Collections)中導(dǎo)出。所有返回對象的類都是非公有的。

??現(xiàn)在的Collections Framework API比導(dǎo)出的45個獨立的公有類的那種實現(xiàn)方式要小得多,每種便利的實現(xiàn)都對應(yīng)一個類。這不僅僅減少了API的數(shù)量,還包括概念上的權(quán)重:程序猿必須掌握的概念的數(shù)量和難度,以便使用API。程序猿知道返回的對象正好有其接口指定的API,因此不需要為實現(xiàn)類去閱讀額外的類文檔。此外,這種工廠方法要求客戶端通過接口而不是實現(xiàn)類來引用返回的對象,這通常是很好的實踐方式(第64項)。

??從Java 8開始,消除了接口不能包含靜態(tài)方法的限制,因此通常沒有理由為接口提供不可實例化的伴隨類。許多公共靜態(tài)成員應(yīng)該放在接口本身中。但請注意,可能仍有必要將大量實現(xiàn)代碼放在這些靜態(tài)方法后面的多帶帶的包私有類中。這是因為Java 8要求接口的所有靜態(tài)成員都是公共的。 Java 9允許私有靜態(tài)方法,但靜態(tài)字段和靜態(tài)成員類的屬性依然是要求是公共的。

??靜態(tài)工廠方法的第四個優(yōu)點是,靜態(tài)工廠方法所返回的對象的類可以隨著每次調(diào)用而變化,這取決于靜態(tài)工廠方法的參數(shù)值。 只要返回的類型是聲明的類的子類都是允許的。返回對象的類也可能隨著發(fā)行版本的不同而不同。

??在EnumSet類(第36項)中有非公有的構(gòu)造方法,只有靜態(tài)工廠方法。在 OpenJDK 實現(xiàn)中的,它們返回兩個子類之一的實例,具體取決于基礎(chǔ)枚舉類型的大小: 如果它有64個或更少的元素,就像大多數(shù)枚舉類型所做的那樣,靜態(tài)工廠返回一個RegularEnumSet實例, 它由單個long的支持;如果枚舉類型有65個或更多元素,則工廠將返回一個由長數(shù)組支持的JumboEnumSet實例。

??這兩個實現(xiàn)類的存在對于客戶端是不可見的。 如果 RegularEnumSet 不再為小枚舉類型提供性能優(yōu)勢可以從未來版本中刪除,沒有任何不良影響。 同樣,未來如果證明有利于性能,則可以添加EnumSet的第三或第四個實現(xiàn)。客戶即不知道也不關(guān)心他們從工廠中獲取的對象的類型,他們只關(guān)心它是EnumSet的一些子類。

??靜態(tài)工廠方法的第五個優(yōu)點是,返回的對象所屬的類,在編寫包含該靜態(tài)工廠方法的類時可以不必存在。 這種靈活的靜態(tài)工廠方法構(gòu)成了服務(wù)提供者框架(Service Provider Framework)的基礎(chǔ),例如JDBC(Java數(shù)據(jù)庫連接,Java Database Connectivity)API。服務(wù)提供者框架是提供者實現(xiàn)服務(wù)的系統(tǒng),系統(tǒng)使實現(xiàn)可用于客戶端,將客戶端與實現(xiàn)分離【微服務(wù)】。

??服務(wù)提供者框架中有三個基本組件:服務(wù)接口【提供者】,代表一個實現(xiàn);提供者注冊API【注冊中心】,提供者用于注冊實現(xiàn); 以及服務(wù)訪問API【消費者】,客戶端使用它來獲取服務(wù)的實例。 服務(wù)訪問API可以允許客戶端指定用于選擇實現(xiàn)的標(biāo)準(zhǔn)。 如果沒有這樣的標(biāo)準(zhǔn),API將返回默認(rèn)實現(xiàn)的實例,或允許客戶端循環(huán)遍歷所有可用的實現(xiàn)。 服務(wù)訪問API是靈活的靜態(tài)工廠,它構(gòu)成了服務(wù)提供者框架的基礎(chǔ)。

??服務(wù)提供者框架的可選第四個組件是服務(wù)提供者接口,它描述了生成服務(wù)接口實例的工廠對象。 在缺少服務(wù)提供者接口的情況下,必須反復(fù)實例化實現(xiàn)(第65項)。 對于JDBC,Connection扮演服務(wù)接口的一部分,DriverManager.registerDriver是提供者注冊API,DriverManager.getConnection是服務(wù)訪問API,Driver是服務(wù)提供者接口。

??服務(wù)提供者框架模式有許多變體。 例如,服務(wù)訪問API可以向客戶端返回比提供者提供的服務(wù)接口更豐富的服務(wù)接口。 這是橋接模式 [Gamma95] 。 依賴注入框架(第5項)可視為強大的服務(wù)提供者。 從Java 6開始,該平臺包含一個通用服務(wù)提供程序框架java.util.ServiceLoader,因此您不需要(通常不應(yīng)該)自己編寫(第59項)。 JDBC不使用ServiceLoader,因為前者早于后者。

??靜態(tài)工廠方法的主要限制在于,類如果不含公有的或者受保護(hù)的構(gòu)造器,就不能被子類化。 例如:不可能將Collections Framework中的任何方便的實現(xiàn)類子類化。但是這也許會因禍得福,因為它鼓勵程序猿使用組合,而不是繼承(第18項),并且要求必須是不可變的(第17項)。

??靜態(tài)工廠方法的第二個缺點是程序員很難找到它們。 它們不像構(gòu)造函數(shù)那樣在API文檔中脫穎而出,因此很難弄清楚如何實例化提供靜態(tài)工廠方法而不是構(gòu)造函數(shù)的類。 Javadoc工具有一天可能會引起對靜態(tài)工廠方法的注意。 在此期間,您可以通過引起對類或接口文檔中的靜態(tài)工廠的注意并遵守常見的命名約定來減少此問題。 以下是靜態(tài)工廠方法的一些常用名稱。 這份清單遠(yuǎn)非詳盡無遺:

from:一種類型轉(zhuǎn)換方法,它接受單個參數(shù)并返回此類型的相應(yīng)實例,例如:Date d = Date.from(instant);

of:一種聚合方法,它接受多個參數(shù)并返回包含它們的此類型的實例,例如:Set faceCards = EnumSet.of(JACK, QUEEN, KING);

valueOf:一個更詳細(xì)的替代方案,例如:BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);

instance or getInstance:返回由其參數(shù)(如果有)描述的實例,但不能說它具有相同的值,例如:StackWalker luke = StackWalker.getInstance(options);

create or newInstance:與instance或getInstance類似,不同之處在于該方法保證每個調(diào)用都返回一個新實例,例如:Object newArray = Array.newInstance(classObject, arrayLen);

getType:與getInstance類似,是在工廠方法位于不同的類中時使用它。 Type指的是工廠方法返回的對象類型,例如:FileStore fs = Files.getFileStore(path);

newType:與newInstance類似,是在工廠方法位于不同的類中的時候使用。Type指的是工廠方法方位的對象類型,例如:BufferedReader br = Files.newBufferedReader(path);

type:獲取Type和new Type一個簡明替代的方法,比如:List litany = Collections.list(legacyLitany);

??總之,靜態(tài)工廠方法和公共構(gòu)造函數(shù)都有它們的用途,理解它們的相對優(yōu)點是值得的。 通常靜態(tài)工廠是優(yōu)選的,不要在第一反應(yīng)就是使用構(gòu)造函數(shù),應(yīng)當(dāng)先考慮使用靜態(tài)工廠方法。


關(guān)注公眾號獲取同步更新

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73876.html

相關(guān)文章

  • 6:避免創(chuàng)建不需要的對象

    摘要:傳遞給構(gòu)造器的參數(shù)本身就是一個實例,功能方面等同于構(gòu)造器創(chuàng)建的所有對象。對于同時提供了靜態(tài)工廠方法第項和構(gòu)造器的不可變類,通常可以使用靜態(tài)工廠方法而不是構(gòu)造器,這樣可以經(jīng)常避免創(chuàng)建不必要的對象。 ??一般來說,最好能重用對象而不是在每次需要的時候就創(chuàng)建一個相同功能的新對象。重用的方式既快速,有流行。如果對象是不可變(immutable)的(第17項),那么就能重復(fù)使用它。 ??作為一個...

    Amio 評論0 收藏0
  • 二章 創(chuàng)建和銷毀對象

    摘要:一個類可以提供一個公共靜態(tài)工廠方法,它僅僅是一第項遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器靜態(tài)工廠和構(gòu)造器有個共同的局限性他們都不能很好地擴(kuò)展到大量的可選參數(shù)。 ??本章涉及創(chuàng)建和銷毀對象,包括何時以及如何創(chuàng)建它們,何時以及如何避免創(chuàng)建它們,如何確保它們被及時銷毀,以及如何管理在銷毀之前必須進(jìn)行的清理操作。 第1項:用靜態(tài)工廠方法代替構(gòu)造器 ??類允許客戶端獲取實例的傳統(tǒng)方法是提供公共構(gòu)造...

    Jeffrrey 評論0 收藏0
  • 2:當(dāng)面臨多個參數(shù)的構(gòu)造器時考慮使用構(gòu)建器

    摘要:因此,最好一開始就考慮使用構(gòu)造器。與使用傳統(tǒng)的重疊構(gòu)造器模式相比,使用模式的客戶端代碼更易于閱讀和編寫,構(gòu)建器也比更加安全。 ??靜態(tài)工廠和構(gòu)造器有個共同的局限性:他們都不能很好地擴(kuò)展到大量的可選參數(shù)。考慮用一個類表示包裝食品外面顯示的營養(yǎng)成分標(biāo)簽。這些標(biāo)簽中有幾個域是必需的:每份的含量、每罐的含量以及每份的卡路里,還有超過20個可選域:總脂肪、飽和脂肪量、轉(zhuǎn)化脂肪、膽固醇、鈉等等。大...

    KavenFan 評論0 收藏0
  • Effective Java 3rd.Edition 翻譯

    摘要:推薦序前言致謝第一章引言第二章創(chuàng)建和銷毀對象第項用靜態(tài)工廠方法代替構(gòu)造器第項遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器第項用私有構(gòu)造器或者枚舉類型強化屬性第項通過私有構(gòu)造器強化不可實例化的能力第項優(yōu)先考慮依賴注入來引用資源第項避免創(chuàng)建不必要的對象 推薦序 前言 致謝 第一章 引言 第二章 創(chuàng)建和銷毀對象 第1項:用靜態(tài)工廠方法代替構(gòu)造器 第2項:遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器 第...

    KoreyLee 評論0 收藏0
  • Effective Java 三版 全文翻譯

    摘要:本章中的大部分內(nèi)容適用于構(gòu)造函數(shù)和方法。第項其他方法優(yōu)先于序列化第項謹(jǐn)慎地實現(xiàn)接口第項考慮使用自定義的序列化形式第項保護(hù)性地編寫方法第項對于實例控制,枚舉類型優(yōu)先于第項考慮用序列化代理代替序列化實例附錄與第版中項目的對應(yīng)關(guān)系參考文獻(xiàn) effective-java-third-edition 介紹 Effective Java 第三版全文翻譯,純屬個人業(yè)余翻譯,不合理的地方,望指正,感激...

    galois 評論0 收藏0

發(fā)表評論

0條評論

趙連江

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<