Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion singleton/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -49,7 +94,7 @@ public enum EnumIvoryTower {
}
```

Then in order to use:
Usage example:

```java
var enumIvoryTower1 = EnumIvoryTower.INSTANCE;
Expand Down
16 changes: 16 additions & 0 deletions singleton/src/main/java/com/iluwatar/singleton/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading