From 1cfbf30d7ec210ee5bc32d710d49a3a0391bed0a Mon Sep 17 00:00:00 2001 From: th-shivam Date: Mon, 6 Oct 2025 10:31:23 +0530 Subject: [PATCH] Fixes missing eager/lazy initialization examples for Hacktoberfest contributors --- singleton/README.md | 47 ++++++++++++++- .../main/java/com/iluwatar/singleton/App.java | 16 ++++++ .../singleton/EagerInitializedSingleton.java | 53 +++++++++++++++++ .../singleton/LazyInitializedSingleton.java | 57 +++++++++++++++++++ .../EagerInitializedSingletonTest.java | 42 ++++++++++++++ .../LazyInitializedSingletonTest.java | 42 ++++++++++++++ 6 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 singleton/src/main/java/com/iluwatar/singleton/EagerInitializedSingleton.java create mode 100644 singleton/src/main/java/com/iluwatar/singleton/LazyInitializedSingleton.java create mode 100644 singleton/src/test/java/com/iluwatar/singleton/EagerInitializedSingletonTest.java create mode 100644 singleton/src/test/java/com/iluwatar/singleton/LazyInitializedSingletonTest.java diff --git a/singleton/README.md b/singleton/README.md index 92505061399e..292b8d1dab57 100644 --- a/singleton/README.md +++ b/singleton/README.md @@ -39,6 +39,51 @@ Sequence diagram ## Programmatic Example of Singleton Pattern in Java +### 1. Eager Initialization + +The instance is created at class loading time. Thread-safe but may waste memory if never used. + +```java +public final class EagerInitializedSingleton { + private static final EagerInitializedSingleton INSTANCE = new EagerInitializedSingleton(); + + private EagerInitializedSingleton() { + if (INSTANCE != null) { + throw new IllegalStateException("Singleton already initialized"); + } + } + + public static EagerInitializedSingleton getInstance() { + return INSTANCE; + } +} +``` + +### 2. Lazy Initialization + +The instance is created only when first requested. Memory efficient but requires synchronization. + +```java +public final class LazyInitializedSingleton { + private static LazyInitializedSingleton instance; + + private LazyInitializedSingleton() { + if (instance != null) { + throw new IllegalStateException("Singleton already initialized"); + } + } + + public static synchronized LazyInitializedSingleton getInstance() { + if (instance == null) { + instance = new LazyInitializedSingleton(); + } + return instance; + } +} +``` + +### 3. Enum Singleton (Recommended) + Joshua Bloch, Effective Java 2nd Edition p.18 > A single-element enum type is the best way to implement a singleton @@ -49,7 +94,7 @@ public enum EnumIvoryTower { } ``` -Then in order to use: +Usage example: ```java var enumIvoryTower1 = EnumIvoryTower.INSTANCE; diff --git a/singleton/src/main/java/com/iluwatar/singleton/App.java b/singleton/src/main/java/com/iluwatar/singleton/App.java index ccc0ff82718f..ebc6f30181e4 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/App.java +++ b/singleton/src/main/java/com/iluwatar/singleton/App.java @@ -72,6 +72,22 @@ public class App { */ public static void main(String[] args) { + // Eager Initialization - Simple and clear example + LOGGER.info("=== Eager Initialization ==="); + var eager1 = EagerInitializedSingleton.getInstance(); + var eager2 = EagerInitializedSingleton.getInstance(); + LOGGER.info("eager1={}", eager1); + LOGGER.info("eager2={}", eager2); + LOGGER.info("Same instance: {}", eager1 == eager2); + + // Lazy Initialization - Simple and clear example + LOGGER.info("=== Lazy Initialization ==="); + var lazy1 = LazyInitializedSingleton.getInstance(); + var lazy2 = LazyInitializedSingleton.getInstance(); + LOGGER.info("lazy1={}", lazy1); + LOGGER.info("lazy2={}", lazy2); + LOGGER.info("Same instance: {}", lazy1 == lazy2); + // eagerly initialized singleton var ivoryTower1 = IvoryTower.getInstance(); var ivoryTower2 = IvoryTower.getInstance(); diff --git a/singleton/src/main/java/com/iluwatar/singleton/EagerInitializedSingleton.java b/singleton/src/main/java/com/iluwatar/singleton/EagerInitializedSingleton.java new file mode 100644 index 000000000000..c4d893e202f5 --- /dev/null +++ b/singleton/src/main/java/com/iluwatar/singleton/EagerInitializedSingleton.java @@ -0,0 +1,53 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.singleton; + +/** + * Eager Initialization Singleton. + * Instance is created at class loading time. + * Thread-safe by default but may waste memory if instance is never used. + */ +public final class EagerInitializedSingleton { + + /** Instance created at class loading time. */ + private static final EagerInitializedSingleton INSTANCE = new EagerInitializedSingleton(); + + /** Private constructor to prevent instantiation. */ + private EagerInitializedSingleton() { + // Prevent reflection attacks + if (INSTANCE != null) { + throw new IllegalStateException("Singleton already initialized"); + } + } + + /** + * Returns the singleton instance. + * + * @return the singleton instance + */ + public static EagerInitializedSingleton getInstance() { + return INSTANCE; + } +} diff --git a/singleton/src/main/java/com/iluwatar/singleton/LazyInitializedSingleton.java b/singleton/src/main/java/com/iluwatar/singleton/LazyInitializedSingleton.java new file mode 100644 index 000000000000..c6fda065c4c1 --- /dev/null +++ b/singleton/src/main/java/com/iluwatar/singleton/LazyInitializedSingleton.java @@ -0,0 +1,57 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.singleton; + +/** + * Lazy Initialization Singleton. + * Instance is created only when first requested. + * Memory efficient but requires synchronization for thread safety. + */ +public final class LazyInitializedSingleton { + + /** Instance variable, initialized only when needed. */ + private static LazyInitializedSingleton instance; + + /** Private constructor to prevent instantiation. */ + private LazyInitializedSingleton() { + // Prevent reflection attacks + if (instance != null) { + throw new IllegalStateException("Singleton already initialized"); + } + } + + /** + * Returns the singleton instance, creating it if necessary. + * Synchronized to ensure thread safety. + * + * @return the singleton instance + */ + public static synchronized LazyInitializedSingleton getInstance() { + if (instance == null) { + instance = new LazyInitializedSingleton(); + } + return instance; + } +} diff --git a/singleton/src/test/java/com/iluwatar/singleton/EagerInitializedSingletonTest.java b/singleton/src/test/java/com/iluwatar/singleton/EagerInitializedSingletonTest.java new file mode 100644 index 000000000000..3613836f7bfd --- /dev/null +++ b/singleton/src/test/java/com/iluwatar/singleton/EagerInitializedSingletonTest.java @@ -0,0 +1,42 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.singleton; + +import static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link EagerInitializedSingleton}. + */ +class EagerInitializedSingletonTest { + + @Test + void testSingletonInstance() { + var instance1 = EagerInitializedSingleton.getInstance(); + var instance2 = EagerInitializedSingleton.getInstance(); + assertSame(instance1, instance2); + } +} diff --git a/singleton/src/test/java/com/iluwatar/singleton/LazyInitializedSingletonTest.java b/singleton/src/test/java/com/iluwatar/singleton/LazyInitializedSingletonTest.java new file mode 100644 index 000000000000..8ded992e0f3d --- /dev/null +++ b/singleton/src/test/java/com/iluwatar/singleton/LazyInitializedSingletonTest.java @@ -0,0 +1,42 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.singleton; + +import static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link LazyInitializedSingleton}. + */ +class LazyInitializedSingletonTest { + + @Test + void testSingletonInstance() { + var instance1 = LazyInitializedSingleton.getInstance(); + var instance2 = LazyInitializedSingleton.getInstance(); + assertSame(instance1, instance2); + } +}