Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

这是AI翻译的帖子。

제이온

[有效 Java] 項目 3. 使用私有建構函式或枚舉類型來保證單例

  • 写作语言: 韓国語
  • 基准国家: 所有国家 country-flag

选择语言

  • 汉语
  • English
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

durumis AI 总结的文章

  • 單例是一種只允許建立一個實例的類別,通常用於建立無狀態物件或唯一的系統元件。
  • 建立單例的方式有:使用公用靜態成員作為 final 欄位的方式、提供靜態工廠方法的方式以及使用枚舉類型的 方式,其中使用枚舉類型的方式最為理想。
  • 在序列化單例類別時,應實作 Serializable 介面,並將所有實例欄位宣告為 transient,以及重新定義 readResolve() 方法。

單例模式

單例模式的概念

單例模式是指只允許創建一個實例的類。單例模式的典型示例包括無狀態對象或唯一的系統 組件。但是,單例類很難測試,除非將其類型定義為接口,並將其實現定義為接口的實現。


創建單例模式的方法

使用 public static 成員作為 final 欄位的方式


public class Elvis {

    public static final Elvis INSTANCE = new Elvis();

    private Elvis() {
    }

    public void speak() {
        System.out.println("elvis");
    }


私有構造函數僅在初始化 Elvis 實例時調用一次,確保它是整個系統中唯一的實例。 但是,可以使用 AccessibleObject.setAccessible() 調用私有構造函數,這種 反射修改方法可以通過在創建第二個對象時拋出異常來阻止。


  • 優點
    • API 明確顯示該類是單例。
    • 簡潔。


提供 public static 的靜態工廠方法的方式

public class Elvis {

    private static final Elvis INSTANCE = new Elvis();

    private Elvis() {
    }

    public static Elvis getInstance() {
        return INSTANCE;
    }

    public void speak() {
        System.out.println("elvis");
    }


除了通過反射修改之外,這種方法也能夠確保在整個系統中只有一個實例。只不過將欄位改為私有, 並使用靜態工廠方法返回對象。


  • 優點
    • 可以在不更改 API 的情況下將其更改為非單例。
      • 例如,靜態工廠方法可以返回每個線程的不同實例。
    • 如果需要,可以更改為泛型單例工廠方法。
    • 可以將靜態工廠的函數引用用作供應商。
      • 例如,可以使用 Supplier<Elvis> 代替 Elvis::getInstance。


如果不需要使用上述優點,最好使用第一種方法。


使用枚舉類型的方式

public enum Elvis {

    INSTANCE;

    public void speak() {
        System.out.println("elvis");
    }


最理想的方式是使用枚舉類型。與前兩種方法相比,它對反射攻擊更安全,代碼也更簡潔。此外, 如下所述,前兩種方法在序列化時需要添加額外的代碼。

但是,需要注意的是,要創建的單例可以繼承接口,但不能繼承類。


單例類序列化時需要注意的事項

如果要序列化使用前兩種方法創建的單例類,除了實現 Serializable 之外,還需要將所有 實例欄位聲明為 transient,並重寫 readResolve() 方法以提供它。


private Object readResolve throws ObjectStreamException {
    return INSTANCE;


來源

제이온
제이온
제이온
제이온
[Effective Java] 項目 1. 考慮使用靜態工廠方法而非建構函式 靜態工廠方法是一種比建構函式更靈活且有效率的建立實例的方法。它們可以具有名稱,並可返回符合特定條件的實例,並可透過快取來提高效能。與單例模式不同,靜態工廠方法可以建立和返回多種類型的實例,並且可以保持彈性,而無需使用反射。

2024年4月27日

[Effective Java] 项目 5. 不要显式地使用资源,而应该使用依赖注入 如果类依赖于外部资源,则最好不要使用单例和静态实用程序类。通过依赖注入,可以提高类的灵活性、可重用性和可测试性,而使用工厂方法模式可以使依赖注入更加高效。

2024年4月28日

[有效 Java] 項目 4. 要阻止實例化,請使用私有建構函數 僅包含靜態方法和欄位的工具類,最好將建構函數的存取修飾符設定為 private,以阻止實例化。 這可以防止使用者誤認為建構函數是自動生成的,並使繼承變得不可能,從而明確表示類別的意圖。

2024年4月28日

邏輯數據模型 邏輯數據模型是將概念數據模型轉換為關係數據庫範式的過程,根據映射規則,將 1:1、1:N、N:M 關係 轉換為關係數據庫中的表格,並通過正規化來確保數據完整性。通過 1NF、2NF、3NF 的正規化過程,對表格進行 優化,消除部分依賴和傳遞依賴。
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

2024年4月9日

概念性數據模型 概念性數據模型是將實體分離並使用 ERD 表示實體間關係的過程。實體是獨立的資訊單位,屬性是 實體擁有的數據。識別碼用於唯一識別實體,關係表示實體間的交互作用。基數性表示實體間的數量關係,可選性表示數據的必需性。
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

2024年4月8日

[并发] 原子操作:内存栅栏和内存顺序 这篇博文将解释在原子操作中如何考虑内存顺序,以及排序选项的重要性。 它将详细解释各种排序选项,例如 Relaxed、Acquire、Release、AcqRel 和 SecCst,以及每个选项的优缺点, 并提供使用示例代码。
곽경직
곽경직
곽경직
곽경직
곽경직

2024年4月12日

在 NestJS 中使用 Prisma Client 模擬單元測試 在應用程式單元測試中,移除外部依賴關係非常重要。透過使用 Prisma ORM 的 Jest 模擬方法,可以輕鬆地進行單元測試。 安裝 jest-mock-extended 套件後,模擬 Prisma Client 並獲得類型支援,建立便利的測試環境。
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

2024年4月2日

[Next.js] 运行时环境注入 了解在 Next.js 中设置构建后环境变量的方法。本文将介绍如何在 Windows 上轻松安装 cross-env 以及修改脚本的方法。它可以有效地用于各种环境变量设置,例如 local、dev、qa、prod 等。
Sunrabbit
Sunrabbit
Sunrabbit
Sunrabbit

2024年3月20日

[Javascript] 物件的結構 (V8) JavaScript 的 Object 在 V8 引擎中根據狀態可以被優化為類似結構體的 Fast 模式或以雜湊表運作的 Dictionary 模式。Fast 模式是針對幾乎固定形式的鍵和值進行優化,速度很快,但當新增新鍵或刪除元素等操作時, 會轉換為 Dictionary 模式,速度會變慢。
곽경직
곽경직
곽경직
곽경직
곽경직

2024年3月18日