From 1894fcf175a227028cdff4f359e2dbabe0ec36ff Mon Sep 17 00:00:00 2001 From: Owen Leung Date: Sun, 27 Aug 2023 19:11:41 +0800 Subject: [PATCH] feat: Add Bill Pugh Impl & Test (#2538) * Add Bill Pugh Impl & Test Add Bill Pugh Impl & Test * Fix formatting * Fix checkstyle error * Reformat file * Reformat file * Fix indentation * Fix comment indent --- .../main/java/com/iluwatar/singleton/App.java | 6 ++ .../singleton/BillPughImplementation.java | 73 +++++++++++++++++++ .../iluwatar/singleton/EnumIvoryTower.java | 3 + .../InitializingOnDemandHolderIdiom.java | 4 + .../ThreadSafeDoubleCheckLocking.java | 7 +- .../ThreadSafeLazyLoadedIvoryTower.java | 8 ++ .../com/iluwatar/singleton/package-info.java | 25 +++++++ .../singleton/BillPughImplementationTest.java | 16 ++++ 8 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 singleton/src/main/java/com/iluwatar/singleton/BillPughImplementation.java create mode 100644 singleton/src/main/java/com/iluwatar/singleton/package-info.java create mode 100644 singleton/src/test/java/com/iluwatar/singleton/BillPughImplementationTest.java diff --git a/singleton/src/main/java/com/iluwatar/singleton/App.java b/singleton/src/main/java/com/iluwatar/singleton/App.java index af09a7ec6..8d7946cae 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 class App { 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 000000000..ba6638618 --- /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; + +/** + *

Bill Pugh Singleton Implementation.

+ * + *

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.

+ * + * @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. + * + *

+ * 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. + *

+ * + * @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 c98157997..8130dc55d 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 @@ package com.iluwatar.singleton; */ 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 013d01722..6cff5b561 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 final class InitializingOnDemandHolderIdiom { * 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 47c01c030..e409432a1 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 @@ package com.iluwatar.singleton; * @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 final class ThreadSafeDoubleCheckLocking { // 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 559363a6c..4d1c25739 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 @@ package com.iluwatar.singleton; */ 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 @@ public final class 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 000000000..bfcfbd77e --- /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; 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 000000000..90a3424e4 --- /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{ + /** + * Create a new singleton test instance using the given 'getInstance' method. + */ + public BillPughImplementationTest() { + super(BillPughImplementation::getInstance); + } +}