創建和銷毀對象

来源:http://www.cnblogs.com/fireway/archive/2017/08/01/7266588.html
-Advertisement-
Play Games

考慮使用靜態工廠方法代替構造器 類可以提供一個公有的靜態工廠方法(public static factory method)來返回一個類的實例。例如,Boolean類的valueOf()方法: public static Boolean valueOf(boolean b) { return (b ...


考慮使用靜態工廠方法代替構造器

類可以提供一個公有的靜態工廠方法(public static factory method)來返回一個類的實例。
例如,Boolean類的valueOf()方法:

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

提供public靜態工廠方法而不是public的構造器的優勢如下:

  1. 靜態工廠方法有名稱,不過要慎重地選擇名稱
    例如,構造器BigIntger(int, int, Random)返回的BigInteger可能為素數,如果用名為BigInteger.probablePrime()的靜態工廠方法顯然更清晰。 
    示例: BigIntegerTest

  2. 不必在每次調用靜態工廠方法的時候都創建一個新對象 
    如果程式經常經常請求創建相同的對象,並且創建對象的代碼很高,則這項技術可以極大地提升性能。 
    示例:BooleanTest 
    當且僅當a==b的時候才有a.equals(b)為true, 如果類保證了這一點, 它的客戶端就可以使用==操作符來代替equals(Object)方法,這樣可以提升性能。

  3. 靜態工廠方法可以返回子類類型的對象 
    API返回的對象對應的子類可以不是公有的,這種方式可以隱藏具體的實現類。 
    這項技術適合於基於介面的框架,介面為靜態工廠提供了自然返回類型。 
    介面不能有靜態方法,因此按照慣例,返回介面的靜態工廠方法是放在一個不可實例化(non-instantiability)的類中。 
    示例: InterfaceCannotStaticTest 

    示例: java.util.Collections是一個不可實例化的類,它提供了不可修改的集合、同步集合的靜態工廠方法。我們模仿其寫了一個簡單例子: MyListTest 

    通過使用這種靜態工廠方法,甚至要求客戶端通過介面來引用被返回的對象,而不是通過它的實現類來引用被返回的對象,這是一種良好的習慣。 為了提升軟體的可維護性和性能,返回對象的(子)類也可能隨著發行版本的不同而不同。 

    示例:EnumSetTest 發行版本1.5中引入java.util.EnumSet沒有公有的構造器,只有靜態工廠方法,返回兩種實現類之一,具體則取決於底層枚舉類型的大小。

    示例:服務提供者框架

  4. 靜態工廠方法在創建參數化類型實例的時候,使得代碼更加簡潔 
    例如,創建一個Map<String, List<String>>對象,在調用參數化類的構造器時,即使類型參數明顯,也必須指明。這通常要求你連接兩次提供類型參數:
    Map<String, List<String>> map = new HashMap<String, List<String>>(); 
    隨著類型參數變得越來越長,越來越複雜,這一冗長的說明也很快變得痛苦起來。 
    但是有了靜態方法,編譯器可以替你找到類型參數,這被稱作類型推導(type inference): 
    Map<String, List<String>> map = HashMap.newInstance(); 
    假設HashMap提供了這個靜態工廠方法:
    public static <K, V> HashMap<K, V> newInstance() { return new HashMap<K, V>(); } 
    總有一天,Java將能夠在構造器調用以及方法調用中執行這些類型推導,但到發行版本1.6為止暫時還無法這麼做。 
    遺憾的是,到發行版本1.6為止,標準的集合實現如HashMap並沒有工廠方法,但是可以把這些方法放在你自己的工具類中。

公有的靜態工廠方法的缺點:

  1. 類如果不含有公有的或者受保護的構造器,靜態工廠方法返回的實例不能被子類化。
  2. 同樣地,對於非公有類(nonpublic classes),靜態工廠方法返回的實例也不能被子類化。 示例: MyListTest
  3. 靜態工廠方法與其它的靜態方法無法被明確區分,不像構造器那樣在api文檔中被明確的標識出來。 所以,在類或介面註釋中關註靜態工廠,使用一些約定俗成的命名
慣用名稱說明
valueOf Returns an instance that has, loosely speaking, the same value as its parameters. Such static factories are effectively type-conversion methods.
of A concise alternative to valueOf , popularized by EnumSet.
getInstance Returns an instance that is described by the parameters but cannot be said to have the same value. In the case of a singleton, getInstance takes no parameters and returns the sole instance.
newInstance Like getInstance , except that newInstance guarantees that each instance returned is distinct from all others.
getType Like getInstance , but used when the factory method is in a different class. Type indicates the type of object returned by the factory method.
newType Like newInstance , but used when the factory method is in a different class. Type indicates the type of object returned by the factory method.

簡而言之,靜態工廠方法和公有構造器都各有用處。 靜態工廠方法通常更加適合,因此切忌第一反應是提供公有的構造器,而不先考慮靜態工廠方法。

遇到多個構造器參數時要考慮用構建器

靜態工廠和構造器有一個共同的局限性:它們都不能很好地擴展到大量的可選參數。考慮用一個類表示一個食品的營養成分表。對於這樣的類,應該用哪個構造器或者靜態方法來編寫呢?

  1. 重疊構造器(telescoping constructor) 
    示例: telescoping_constructor/NutritionFacts 
    ① 當有許多參數的時候,客戶端代碼會很難編寫,並且仍然較難以閱讀。 
    ② 如果讀者想知道那些值是什麼意思,必須很仔細地數著這些參數來探個究竟。如果客戶端不小心顛倒了其中兩個參數的順序,編譯器也不會出錯,但是在程式運行時會出現錯誤行為。
  2. JavaBeans模式:調用一個無參構造器來創建對象,然後調用setter()方法來設置每個必要的參數,以及每個相關的可選參數。
    示例: javabeans/NutritionFacts 
    ① 無法保證一致性:JavaBean模式自身有著很嚴重的缺點,因為構造過程被分到了幾個調用中,在構造過程中JavaBean可能處在不一致的狀態。類無法僅僅通過檢驗構造器參數的有效性來保證一致性。試圖使用處於不一致狀態的對象,將會導致失敗,這種失敗調試起來十分困難。 
    ② 阻止了把類做成不可變,這就需要程式員付出額外的努力來確保它的線程安全。
  3. Builder模式 
    示例:builder/NutritionFacts 
    這樣的客戶端代碼很容易編寫,而且易讀。Builder模式模擬了具名的可選參數,就像Python一樣。 
    對參數加強約束條件: build()方法檢驗或者多個setter()方法檢驗這些約束條件,如果該約束條件沒有得到滿足,就拋出IllegalStateException或IllegalArgumentException。 
    設置了參數的Builder生成了一個很好的抽象工廠(Abstract Factory)。Java中的Class對象就是一個抽象工廠,用newInstance()方法充當build()方法的一部分。 
    Builder模式也有它自身不足,為了創建對象,必須先創建它的構建器,它還會比重疊構造器模式更加冗長,因此只有在很多參數(4個以上)的時候才考慮使用Builder模式。但是要記住,將來你可能需要添加參數,如果一開始就使用構造器或者靜態工廠,等到類需要多個參數時才添加構建器,就無法控制,那些過時的構造器或者靜態工廠顯得十分不協調。因此通常最好一開始就使用構建器。

用私有構造器或者枚舉類型強化Singleton屬性

Singleton指僅僅被實例化一次的類。Singleton通常被用來代表那些本質上唯一的系統組件。 
在Java 1.5發行版本之前,實現Singleton有兩種方法。這兩種方法都要把構造器保持為私有的,並導出公有的靜態成員,以便允許客戶端能夠訪問該類的唯一實例。 
第一種方法,公有靜態成員是一個final域。示例: field/Elvis.java 
私有構造器僅被調用一次,用來實例化公有的靜態域Elvis.INSTANCE。 
但要提醒一點:享有特權的客戶端可以藉助AccessibleObject.setAccessible()方法,通過反射機制調用私有構造器,示例:ModifyingSingleton 。如果需要抵禦這種攻擊,可以修改構造器,讓它在被要求創建第二個實例的時候拋出異常。

通過私有構造器強化不可實例化的能力

避免創建不必要的對象

消除過期的對象引用

避免使用終結方法

參考資料


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.什麼是委托? 1.1委托是一種引用類型,該類型適用於將方法用特定的簽名封裝,我們可以將委托理解為一個封裝了函數指針和方法的特殊類型。 1.2使用委托我們可以將方法封裝在委托中,然後調用委托就可以調用其中的方法 2.委托的基本聲明格式 修飾符 delegate 返回類型 委托名(參數列表)——返回 ...
  • 前面講了 "文件的上傳" ,今天來聊聊文件的下載。 老規矩,還是從最簡單粗暴的開始。那麼多簡單算簡單?多粗暴算粗暴?我告訴你可以不寫一句代碼,你信嗎?直接把一個文件往IIS伺服器上一扔,就支持下載。還TM麽可以斷點續傳(IIS服務端預設支持)。 在貼代碼之前先來瞭解下什麼是斷點續傳( 這裡說的是下載 ...
  • IdentityServer4 是一個提供 認證服務,單點登錄/登出(SSO),API訪問控制,聯合認證通道的可定製、免費商業支持的框架。 ...
  • IdentityServer4 是一個提供 認證服務,單點登錄/登出(SSO),API訪問控制,聯合認證通道的可定製、免費商業支持的框架。 ...
  • IdentityServer4 是一個提供 認證服務,單點登錄/登出(SSO),API訪問控制,聯合認證通道的可定製、免費商業支持的框架。 ...
  • IdentityServer4 是一個提供 認證服務,單點登錄/登出(SSO),API訪問控制,聯合認證通道的可定製、免費商業支持的框架。 ...
  • 非同步非常重要的一點就是不會使當前線程阻塞,C#主要通過委托機制來實現非同步編程。 ...
  • 公司的核心業務合作伙伴淘寶網,最近出現泄漏用戶信息的現象,找了好久找不到根源,於是乎,淘寶那邊決定對所有敏感數據進行加密,從出口和入口都走密文,於是乎,我們的工作量就來了。 我們的一個底單資料庫,存儲了大量淘寶賣家和買家的訂單列印,申請單號,發貨,回收單號等等操作的日誌,大概有10億左右數據(自動刪 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...