decrease number of checkstyle errors in singleton, strategy and visitor patterns #1021 (#1054)

* fix checkstlye errors - visitor pattern

* fix checkstlye errors - strategy pattern

* fix checkstlye errors - singleton pattern
This commit is contained in:
Leonóra Dér
2019-10-31 18:54:13 +01:00
committed by Ilkka Seppälä
parent 1eb1961f1b
commit 3b1a28149b
39 changed files with 182 additions and 201 deletions

View File

@ -27,40 +27,40 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Singleton pattern ensures that the class can have only one existing instance per Java classloader
* instance and provides global access to it.
* <p>
* One of the risks of this pattern is that bugs resulting from setting a singleton up in a
* <p>Singleton pattern ensures that the class can have only one existing instance per Java
* classloader instance and provides global access to it.</p>
*
* <p>One of the risks of this pattern is that bugs resulting from setting a singleton up in a
* distributed environment can be tricky to debug, since it will work fine if you debug with a
* single classloader. Additionally, these problems can crop up a while after the implementation of
* a singleton, since they may start out synchronous and only become async with time, so you it may
* not be clear why you are seeing certain changes in behaviour.
* <p>
* There are many ways to implement the Singleton. The first one is the eagerly initialized instance
* in {@link IvoryTower}. Eager initialization implies that the implementation is thread safe. If
* you can afford giving up control of the instantiation moment, then this implementation will suit
* you fine.
* <p>
* The other option to implement eagerly initialized Singleton is enum based Singleton. The example
* is found in {@link EnumIvoryTower}. At first glance the code looks short and simple. However, you
* should be aware of the downsides including committing to implementation strategy, extending the
* enum class, serializability and restrictions to coding. These are extensively discussed in Stack
* Overflow:
* not be clear why you are seeing certain changes in behaviour.</p>
*
* <p>There are many ways to implement the Singleton. The first one is the eagerly initialized
* instance in {@link IvoryTower}. Eager initialization implies that the implementation is thread
* safe. If you can afford giving up control of the instantiation moment, then this implementation
* will suit you fine.</p>
*
* <p>The other option to implement eagerly initialized Singleton is enum based Singleton. The
* example is found in {@link EnumIvoryTower}. At first glance the code looks short and simple.
* However, you should be aware of the downsides including committing to implementation strategy,
* extending the enum class, serializability and restrictions to coding. These are extensively
* discussed in Stack Overflow:
* http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
* -a-singleton-with-javas-enum
* <p>
* {@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on
* -a-singleton-with-javas-enum</p>
*
* <p>{@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on
* demand. The downside is that it is very slow to access since the whole access method is
* synchronized.
* <p>
* Another Singleton implementation that is initialized on demand is found in
* synchronized.</p>
*
* <p>Another Singleton implementation that is initialized on demand is found in
* {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than
* {@link ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but
* only the method internals on specific conditions.
* <p>
* Yet another way to implement thread safe lazily initialized Singleton can be found in
* only the method internals on specific conditions.</p>
*
* <p>Yet another way to implement thread safe lazily initialized Singleton can be found in
* {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8
* API level to work.
* API level to work.</p>
*/
public class App {

View File

@ -24,10 +24,10 @@
package com.iluwatar.singleton;
/**
* Enum based singleton implementation. Effective Java 2nd Edition (Joshua Bloch) p. 18
* <p>Enum based singleton implementation. Effective Java 2nd Edition (Joshua Bloch) p. 18</p>
*
* This implementation is thread safe, however adding any other method and its thread safety
* is developers responsibility.
* <p>This implementation is thread safe, however adding any other method and its thread safety
* is developers responsibility.</p>
*/
public enum EnumIvoryTower {

View File

@ -24,16 +24,16 @@
package com.iluwatar.singleton;
/**
* The Initialize-on-demand-holder idiom is a secure way of creating a lazy initialized singleton
* object in Java.
* <p>
* The technique is as lazy as possible and works in all known versions of Java. It takes advantage
* of language guarantees about class initialization, and will therefore work correctly in all
* Java-compliant compilers and virtual machines.
* <p>
* The inner class is referenced no earlier (and therefore loaded no earlier by the class loader) than
* the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special
* language constructs (i.e. volatile or synchronized).
* <p>The Initialize-on-demand-holder idiom is a secure way of creating a lazy initialized singleton
* object in Java.</p>
*
* <p>The technique is as lazy as possible and works in all known versions of Java. It takes
* advantage of language guarantees about class initialization, and will therefore work correctly
* in all Java-compliant compilers and virtual machines.</p>
*
* <p>The inner class is referenced no earlier (and therefore loaded no earlier by the class loader)
* than the moment that getInstance() is called. Thus, this solution is thread-safe without
* requiring special language constructs (i.e. volatile or synchronized).</p>
*
*/
public final class InitializingOnDemandHolderIdiom {
@ -44,6 +44,8 @@ public final class InitializingOnDemandHolderIdiom {
private InitializingOnDemandHolderIdiom() {}
/**
* Sigleton instance.
*
* @return Singleton instance
*/
public static InitializingOnDemandHolderIdiom getInstance() {

View File

@ -24,11 +24,11 @@
package com.iluwatar.singleton;
/**
* Double check locking
* <p>
* http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
* <p>
* Broken under Java 1.4.
* <p>Double check locking.</p>
*
* <p>http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html</p>
*
* <p>Broken under Java 1.4.</p>
*
* @author mortezaadi@gmail.com
*/
@ -60,17 +60,21 @@ public final class ThreadSafeDoubleCheckLocking {
// Joshua Bloch "Effective Java, Second Edition", p. 283-284
var result = instance;
// Check if singleton instance is initialized. If it is initialized then we can return the instance.
// Check if singleton instance is initialized.
// If it is initialized then we can return the instance.
if (result == null) {
// It is not initialized but we cannot be sure because some other thread might have initialized it
// in the meanwhile. So to make sure we need to lock on an object to get mutual exclusion.
// It is not initialized but we cannot be sure because some other thread might have
// initialized it in the meanwhile.
// So to make sure we need to lock on an object to get mutual exclusion.
synchronized (ThreadSafeDoubleCheckLocking.class) {
// Again assign the instance to local variable to check if it was initialized by some other thread
// while current thread was blocked to enter the locked zone. If it was initialized then we can
// return the previously created instance just like the previous null check.
// Again assign the instance to local variable to check if it was initialized by some
// other thread while current thread was blocked to enter the locked zone.
// If it was initialized then we can return the previously created instance
// just like the previous null check.
result = instance;
if (result == null) {
// The instance is still not initialized so we can safely (no other thread can enter this zone)
// 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();
}

View File

@ -24,11 +24,11 @@
package com.iluwatar.singleton;
/**
* Thread-safe Singleton class. The instance is lazily initialized and thus needs synchronization
* mechanism.
* <p>Thread-safe Singleton class. The instance is lazily initialized and thus needs synchronization
* mechanism.</p>
*
* Note: if created by reflection then a singleton will not be created but multiple options in the
* same classloader
* <p>Note: if created by reflection then a singleton will not be created but multiple options
* in the same classloader</p>
*/
public final class ThreadSafeLazyLoadedIvoryTower {

View File

@ -26,9 +26,7 @@ package com.iluwatar.singleton;
import org.junit.jupiter.api.Test;
/**
*
* Application test
*
* Application test.
*/
public class AppTest {

View File

@ -24,14 +24,14 @@
package com.iluwatar.singleton;
/**
* Date: 12/29/15 - 19:20 PM
* Date: 12/29/15 - 19:20 PM.
*
* @author Jeroen Meulemeester
*/
public class EnumIvoryTowerTest extends SingletonTest<EnumIvoryTower> {
/**
* Create a new singleton test instance using the given 'getInstance' method
* Create a new singleton test instance using the given 'getInstance' method.
*/
public EnumIvoryTowerTest() {
super(() -> EnumIvoryTower.INSTANCE);

View File

@ -24,14 +24,15 @@
package com.iluwatar.singleton;
/**
* Date: 12/29/15 - 19:22 PM
* Date: 12/29/15 - 19:22 PM.
*
* @author Jeroen Meulemeester
*/
public class InitializingOnDemandHolderIdiomTest extends SingletonTest<InitializingOnDemandHolderIdiom> {
public class InitializingOnDemandHolderIdiomTest
extends SingletonTest<InitializingOnDemandHolderIdiom> {
/**
* Create a new singleton test instance using the given 'getInstance' method
* Create a new singleton test instance using the given 'getInstance' method.
*/
public InitializingOnDemandHolderIdiomTest() {
super(InitializingOnDemandHolderIdiom::getInstance);

View File

@ -24,14 +24,14 @@
package com.iluwatar.singleton;
/**
* Date: 12/29/15 - 19:23 PM
* Date: 12/29/15 - 19:23 PM.
*
* @author Jeroen Meulemeester
*/
public class IvoryTowerTest extends SingletonTest<IvoryTower> {
/**
* Create a new singleton test instance using the given 'getInstance' method
* Create a new singleton test instance using the given 'getInstance' method.
*/
public IvoryTowerTest() {
super(IvoryTower::getInstance);

View File

@ -23,8 +23,10 @@
package com.iluwatar.singleton;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static java.time.Duration.ofMillis;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTimeout;
import java.util.ArrayList;
import java.util.List;
@ -34,19 +36,17 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Supplier;
import static java.time.Duration.ofMillis;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTimeout;
import org.junit.jupiter.api.Test;
/**
* This class provides several test case that test singleton construction.
* <p>This class provides several test case that test singleton construction.</p>
*
* The first proves that multiple calls to the singleton getInstance object are the same when called
* in the SAME thread. The second proves that multiple calls to the singleton getInstance object are
* the same when called in the DIFFERENT thread.
* <p>The first proves that multiple calls to the singleton getInstance object are the same when
* called in the SAME thread. The second proves that multiple calls to the singleton getInstance
* object are the same when called in the DIFFERENT thread.</p>
*
* <p>Date: 12/29/15 - 19:25 PM</p>
*
* Date: 12/29/15 - 19:25 PM
* @param <S> Supplier method generating singletons
* @author Jeroen Meulemeester
* @author Richard Jones
@ -54,12 +54,12 @@ import static org.junit.jupiter.api.Assertions.assertTimeout;
public abstract class SingletonTest<S> {
/**
* The singleton's getInstance method
* The singleton's getInstance method.
*/
private final Supplier<S> singletonInstanceMethod;
/**
* Create a new singleton test instance using the given 'getInstance' method
* Create a new singleton test instance using the given 'getInstance' method.
*
* @param singletonInstanceMethod The singleton's getInstance method
*/
@ -68,7 +68,7 @@ public abstract class SingletonTest<S> {
}
/**
* Test the singleton in a non-concurrent setting
* Test the singleton in a non-concurrent setting.
*/
@Test
public void testMultipleCallsReturnTheSameObjectInSameThread() {
@ -83,7 +83,7 @@ public abstract class SingletonTest<S> {
}
/**
* Test singleton instance in a concurrent setting
* Test singleton instance in a concurrent setting.
*/
@Test
public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws Exception {

View File

@ -23,34 +23,35 @@
package com.iluwatar.singleton;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.junit.Test;
/**
* Date: 12/29/15 - 19:26 PM
* Date: 12/29/15 - 19:26 PM.
*
* @author Jeroen Meulemeester
*/
public class ThreadSafeDoubleCheckLockingTest extends SingletonTest<ThreadSafeDoubleCheckLocking> {
/**
* Create a new singleton test instance using the given 'getInstance' method
* Create a new singleton test instance using the given 'getInstance' method.
*/
public ThreadSafeDoubleCheckLockingTest() {
super(ThreadSafeDoubleCheckLocking::getInstance);
}
/**
* Test creating new instance by refection
* Test creating new instance by refection.
*/
@Test(expected = InvocationTargetException.class)
public void testCreatingNewInstanceByRefection() throws Exception {
ThreadSafeDoubleCheckLocking instance1 = ThreadSafeDoubleCheckLocking.getInstance();
Constructor constructor = ThreadSafeDoubleCheckLocking.class.getDeclaredConstructor();
constructor.setAccessible(true);
ThreadSafeDoubleCheckLocking instance2 = (ThreadSafeDoubleCheckLocking) constructor.newInstance(null);
ThreadSafeDoubleCheckLocking instance2 =
(ThreadSafeDoubleCheckLocking) constructor.newInstance(null);
}
}

View File

@ -24,14 +24,15 @@
package com.iluwatar.singleton;
/**
* Date: 12/29/15 - 19:26 PM
* Date: 12/29/15 - 19:26 PM.
*
* @author Jeroen Meulemeester
*/
public class ThreadSafeLazyLoadedIvoryTowerTest extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
public class ThreadSafeLazyLoadedIvoryTowerTest
extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
/**
* Create a new singleton test instance using the given 'getInstance' method
* Create a new singleton test instance using the given 'getInstance' method.
*/
public ThreadSafeLazyLoadedIvoryTowerTest() {
super(ThreadSafeLazyLoadedIvoryTower::getInstance);