Repository: iluwatar/java-design-patterns
Issue: More Singleton wisdom
Labels: type: enhancement
info: good first issue
epic: design
status: stale

Analyze the following article from Oracle: https://community.oracle.com/docs/DOC-918906

Improve Singleton examples and their documentation where necessary.


Issue comments:
@iluwatar There is an issue #188 where concern regarding lazy loading of Singleton is raised. I was going through the singleton documentation yesterday and found that the disadvantages of approaches are not discussed. We should document that the lazy loading example with `synchronized` keyword is ok for small applications but actually is too slow for production and should not be preferred.

http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing-a-singleton-with-javas-enum covers downsides of `Enum` based singleton.

Misko Hevery has discussed Singleton vs single instance in this blog post http://misko.hevery.com/2008/08/25/root-cause-of-singletons/
In his blog Misko discusses that there is nothing wrong in having a single instance of something, like having a single application scope object maintained by IoC containers, they don't have private constructors or global instance variable. The singletonness is maintained by container. We can also include this in FAQ "Are Singletons bad?" or some better name.
Further references which I found useful:
- http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
- http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/
- http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

I feel much can be said about Singletons so we need to figure out how we are going to address this. Your thoughts?

I haven't read those links yet but by my own experience I know that in some simple scenarios a singleton can be perfectly replaced by a uninstantiable class. I think this should be written as a footnote somewhere if we already have a place for these things.

There are interesting findings in the Oracle's article particularly about double-checked locking. However, I think our implementation [ThreadSafeDoubleCheckLocking](https://github.com/iluwatar/java-design-patterns/blob/master/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java) is correct.

Those are excellent articles @npathai :+1:  Thanks for sharing.

@iluwatar  Is there an implementation of Singleton with Enum in this repo ? I think Effective Java recommends that we use Enum as Singleton as it is the most bulletproof construction of singleton.

Edit:- There is one...saw it just now.

Yes but there are known downsides for that. EJ is old and much have been learned since then.

An issue is that it will have the following public static methods:

```
    public static Foo[] values()
    public static Foo valueOf(String name)
```

http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

@iluwatar I had linked this question in my previous comment. :+1: though. 

Ah, didn't notice that. This thread is getting long...

@iluwatar is this task still open. Can you assign this to me? 
I am reading about singletons
Task is: "Improve Singleton examples and their documentation where necessary." ?
Great, go ahead @sanghisha145 
> @iluwatar is this task still open. Can you assign this to me?
> I am reading about singletons
> Task is: "Improve Singleton examples and their documentation where necessary." ?

Hey @sanghisha145, Any updates?
hey @iluwatar , @ohbus  is this issue still open. You can assign this to me. 
I will try to finish it within 1 month.
and I will ask for help if necessary from you all.
After a long period of not receiving any updates from @sanghisha145

I am assigning this issue to @Vikashratn.

Good Luck!! 
@Vikashratn are you working on this?
hey @Vikashratn are u still working on this issue

This issue is free for taking again.
```java
public class Element {
	public static final Element NONE = new Element();
	public static final Element WATER = new Water();
	public static final Element EARTH = new Earth();
	public static final Element FIRE = new Fire();
	public static final Element AIR = new Air();
	
	public void printName() {
		System.out.println("Element is: "+getName());
	}
	
	public String getName() {
		return "None";
	}
}
public class Water extends Element {
	public String getName() {
		return "Water";
	}
}
public class Earth extends Element {
	public String getName() {
		return "Earth";
	}
}
public class Fire extends Element {
	public String getName() {
		return "Fire";
	}
}
public class Air extends Element {
	public String getName() {
		return "Air";
	}
}
```

Why isn't something like this included in the singleton as a option?
Yes you could create more instances from that class, but this unique instance is technically also a singleton.
Which you can identify.

It provides a aspect that enums can not provide. If you have singleton instances that require expand ability, adding new elements (singletons) later, is not possible with enums without having resort to something like reflection/asm.

ofcourse you could just move functions from the enum into a interface too and let the enum extend them and have multiple enums.

Also this singleton pattern shown here is also really powerful with the factory pattern.
Without the enum overhead that exists.
Hi, I'm new to this project. How would i go about contributing to it?Thanks.
@OtherHorizon see https://github.com/iluwatar/java-design-patterns/wiki/01.-How-to-contribute
Is this issue still free so I can be assigned? recently I was reading about the design pattern and I want to contribute.
@ohbus @iluwatar 
Ok @Omar-ahmed314, this is assigned for you
Thank you for considering me, @iluwatar , may I know the deadline for this issue? away from the deadline of hacktoberfest
I'd be happy for you if you completed it during the hacktober month 😀
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

We should document Bill Pugh's singleton solution
@iluwatar, I would like to contribute, can I be assigned to this issue? 
That's excellent, please go ahead @jasokolowska 
This issue has been automatically marked as stale because it has not had recent activity. The issue will be unassigned if no further activity occurs. Thank you for your contributions.

@iluwatar I think in the current Singleton example we are just missing Bill Pugh's singleton solution. I'm happy to take over if needed 
This issue has been automatically marked as stale because it has not had recent activity. The issue will be unassigned if no further activity occurs. Thank you for your contributions.


Pull request review comments:
<picture><img alt="6% of developers fix this issue" src="https://lift.sonatype.com/api/commentimage/fixrate/6/display.svg"></picture>

<b>*[ObjectToString](https://errorprone.info/bugpattern/ObjectToString):</b>*  BillPughImplementation is final and does not override Object.toString, so converting it to a string will print its identity (e.g. `BillPughImplementation@4488aabb`) instead of useful information.

---

<details><summary>ℹ️ Expand to see all <b>@sonatype-lift</b> commands</summary>

You can reply with the following commands. For example, reply with ***@sonatype-lift ignoreall*** to leave out all findings.
| **Command** | **Usage** |
| ------------- | ------------- |
| `@sonatype-lift ignore` | Leave out the above finding from this PR |
| `@sonatype-lift ignoreall` | Leave out all the existing findings from this PR |
| `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified `file\|issue\|path\|tool` from Lift findings by updating your config.toml file |

**Note:** When talking to LiftBot, you need to **refresh** the page to see its response.
<sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) to add LiftBot to another repo.</sub></details>


<picture><img alt="6% of developers fix this issue" src="https://lift.sonatype.com/api/commentimage/fixrate/6/display.svg"></picture>

<b>*[ObjectToString](https://errorprone.info/bugpattern/ObjectToString):</b>*  BillPughImplementation is final and does not override Object.toString, so converting it to a string will print its identity (e.g. `BillPughImplementation@4488aabb`) instead of useful information.

---

<details><summary>ℹ️ Expand to see all <b>@sonatype-lift</b> commands</summary>

You can reply with the following commands. For example, reply with ***@sonatype-lift ignoreall*** to leave out all findings.
| **Command** | **Usage** |
| ------------- | ------------- |
| `@sonatype-lift ignore` | Leave out the above finding from this PR |
| `@sonatype-lift ignoreall` | Leave out all the existing findings from this PR |
| `@sonatype-lift exclude <file\|issue\|path\|tool>` | Exclude specified `file\|issue\|path\|tool` from Lift findings by updating your config.toml file |

**Note:** When talking to LiftBot, you need to **refresh** the page to see its response.
<sub>[Click here](https://github.com/apps/sonatype-lift/installations/new) to add LiftBot to another repo.</sub></details>



Patch that resolved the issue:
diff --git a/singleton/src/main/java/com/iluwatar/singleton/App.java b/singleton/src/main/java/com/iluwatar/singleton/App.java
index af09a7ec6828..8d7946cae95d 100644
--- a/singleton/src/main/java/com/iluwatar/singleton/App.java
+++ b/singleton/src/main/java/com/iluwatar/singleton/App.java
@@ -100,5 +100,11 @@ public static void main(String[] args) {
     LOGGER.info(demandHolderIdiom.toString());
     var demandHolderIdiom2 = InitializingOnDemandHolderIdiom.getInstance();
     LOGGER.info(demandHolderIdiom2.toString());
+
+    // initialize singleton using Bill Pugh's implementation
+    var billPughSingleton = BillPughImplementation.getInstance();
+    LOGGER.info(billPughSingleton.toString());
+    var billPughSingleton2 = BillPughImplementation.getInstance();
+    LOGGER.info(billPughSingleton2.toString());
   }
 }
diff --git a/singleton/src/main/java/com/iluwatar/singleton/BillPughImplementation.java b/singleton/src/main/java/com/iluwatar/singleton/BillPughImplementation.java
new file mode 100644
index 000000000000..ba66386181df
--- /dev/null
+++ b/singleton/src/main/java/com/iluwatar/singleton/BillPughImplementation.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+/**
+ * <p>Bill Pugh Singleton Implementation.</p>
+ *
+ * <p>This implementation of the singleton design pattern takes advantage of the
+ * Java memory model's guarantees about class initialization. Each class is
+ * initialized only once, when it is first used. If the class hasn't been used
+ * yet, it won't be loaded into memory, and no memory will be allocated for
+ * a static instance. This makes the singleton instance lazy-loaded and thread-safe.</p>
+ *
+ * @author owen.leung2@gmail.com
+ */
+public final class BillPughImplementation {
+
+  /**
+   * Private constructor to prevent instantiation from outside the class.
+   */
+  private BillPughImplementation() {
+    // private constructor
+  }
+
+  /**
+   * The InstanceHolder is a static inner class and it holds the Singleton instance.
+   * It is not loaded into memory until the getInstance() method is called.
+   */
+  private static class InstanceHolder {
+    /**
+     * Singleton instance of the class.
+     */
+    private static BillPughImplementation instance = new BillPughImplementation();
+  }
+
+  /**
+   * Public accessor for the singleton instance.
+   *
+   * <p>
+   * When this method is called, the InstanceHolder is loaded into memory
+   * and creates the Singleton instance. This method provides a global access point
+   * for the singleton instance.
+   * </p>
+   *
+   * @return an instance of the class.
+   */
+  // global access point
+  public static BillPughImplementation getInstance() {
+    return InstanceHolder.instance;
+  }
+}
diff --git a/singleton/src/main/java/com/iluwatar/singleton/EnumIvoryTower.java b/singleton/src/main/java/com/iluwatar/singleton/EnumIvoryTower.java
index c98157997f90..8130dc55dd70 100644
--- a/singleton/src/main/java/com/iluwatar/singleton/EnumIvoryTower.java
+++ b/singleton/src/main/java/com/iluwatar/singleton/EnumIvoryTower.java
@@ -32,6 +32,9 @@
  */
 public enum EnumIvoryTower {
 
+  /**
+   * The singleton instance of the class, created by the Java enum singleton pattern.
+   */
   INSTANCE;
 
   @Override
diff --git a/singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java b/singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java
index 013d01722796..6cff5b561a92 100644
--- a/singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java
+++ b/singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java
@@ -58,6 +58,10 @@ public static InitializingOnDemandHolderIdiom getInstance() {
    * Provides the lazy-loaded Singleton instance.
    */
   private static class HelperHolder {
+
+    /**
+     * Singleton instance of the class.
+     */
     private static final InitializingOnDemandHolderIdiom INSTANCE =
         new InitializingOnDemandHolderIdiom();
   }
diff --git a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java
index 47c01c030334..e409432a1945 100644
--- a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java
+++ b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java
@@ -34,7 +34,9 @@
  * @author mortezaadi@gmail.com
  */
 public final class ThreadSafeDoubleCheckLocking {
-
+  /**
+   * Singleton instance of the class, declared as volatile to ensure atomic access by multiple threads.
+   */
   private static volatile ThreadSafeDoubleCheckLocking instance;
 
   /**
@@ -73,7 +75,8 @@ public static ThreadSafeDoubleCheckLocking getInstance() {
           // The instance is still not initialized so we can safely
           // (no other thread can enter this zone)
           // create an instance and make it our singleton instance.
-          instance = result = new ThreadSafeDoubleCheckLocking();
+          result = new ThreadSafeDoubleCheckLocking();
+          instance = result;
         }
       }
     }
diff --git a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java
index 559363a6c998..4d1c25739673 100644
--- a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java
+++ b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java
@@ -31,8 +31,14 @@
  */
 public final class ThreadSafeLazyLoadedIvoryTower {
 
+  /**
+   * Singleton instance of the class, declared as volatile to ensure atomic access by multiple threads.
+   */
   private static volatile ThreadSafeLazyLoadedIvoryTower instance;
 
+  /**
+   * Private constructor to prevent instantiation from outside the class.
+   */
   private ThreadSafeLazyLoadedIvoryTower() {
     // Protect against instantiation via reflection
     if (instance != null) {
@@ -42,6 +48,8 @@ private ThreadSafeLazyLoadedIvoryTower() {
 
   /**
    * The instance doesn't get created until the method is called for the first time.
+   *
+   * @return an instance of the class.
    */
   public static synchronized ThreadSafeLazyLoadedIvoryTower getInstance() {
     if (instance == null) {
diff --git a/singleton/src/main/java/com/iluwatar/singleton/package-info.java b/singleton/src/main/java/com/iluwatar/singleton/package-info.java
new file mode 100644
index 000000000000..bfcfbd77e344
--- /dev/null
+++ b/singleton/src/main/java/com/iluwatar/singleton/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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;


Test patch:
diff --git a/singleton/src/test/java/com/iluwatar/singleton/BillPughImplementationTest.java b/singleton/src/test/java/com/iluwatar/singleton/BillPughImplementationTest.java
new file mode 100644
index 000000000000..90a3424e412c
--- /dev/null
+++ b/singleton/src/test/java/com/iluwatar/singleton/BillPughImplementationTest.java
@@ -0,0 +1,16 @@
+package com.iluwatar.singleton;
+
+/**
+ * Date: 06/18/23 - 16:29 PM.
+ *
+ * @author Owen Leung
+ */
+public class BillPughImplementationTest
+        extends SingletonTest<BillPughImplementation>{
+    /**
+     * Create a new singleton test instance using the given 'getInstance' method.
+     */
+    public BillPughImplementationTest() {
+        super(BillPughImplementation::getInstance);
+    }
+}