亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

趙連江 / 3290人閱讀

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

??這兩個(gè)實(shí)現(xiàn)類的存在對(duì)于客戶端是不可見(jiàn)的。 如果 RegularEnumSet 不再為小枚舉類型提供性能優(yōu)勢(shì)可以從未來(lái)版本中刪除,沒(méi)有任何不良影響。 同樣,未來(lái)如果證明有利于性能,則可以添加EnumSet的第三或第四個(gè)實(shí)現(xiàn)??蛻艏床恢酪膊魂P(guān)心他們從工廠中獲取的對(duì)象的類型,他們只關(guān)心它是EnumSet的一些子類。

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

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

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

??服務(wù)提供者框架模式有許多變體。 例如,服務(wù)訪問(wèn)API可以向客戶端返回比提供者提供的服務(wù)接口更豐富的服務(wù)接口。 這是橋接模式 [Gamma95] 。 依賴注入框架(第5項(xiàng))可視為強(qiáng)大的服務(wù)提供者。 從Java 6開(kāi)始,該平臺(tái)包含一個(gè)通用服務(wù)提供程序框架java.util.ServiceLoader,因此您不需要(通常不應(yīng)該)自己編寫(xiě)(第59項(xiàng))。 JDBC不使用ServiceLoader,因?yàn)榍罢咴缬诤笳摺?/p>

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

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

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

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

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

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

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

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

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

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

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


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

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/73876.html

相關(guān)文章

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

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

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

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

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

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

    KavenFan 評(píng)論0 收藏0
  • Effective Java 3rd.Edition 翻譯

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

    KoreyLee 評(píng)論0 收藏0
  • Effective Java 三版 全文翻譯

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

    galois 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

趙連江

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<