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; import org.slf4j.LoggerFactory;
/** /**
* Singleton pattern ensures that the class can have only one existing instance per Java classloader * <p>Singleton pattern ensures that the class can have only one existing instance per Java
* instance and provides global access to it. * 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 * <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 * 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 * 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 * 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. * 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 * <p>There are many ways to implement the Singleton. The first one is the eagerly initialized
* in {@link IvoryTower}. Eager initialization implies that the implementation is thread safe. If * instance in {@link IvoryTower}. Eager initialization implies that the implementation is thread
* you can afford giving up control of the instantiation moment, then this implementation will suit * safe. If you can afford giving up control of the instantiation moment, then this implementation
* you fine. * will suit you fine.</p>
* <p> *
* The other option to implement eagerly initialized Singleton is enum based Singleton. The example * <p>The other option to implement eagerly initialized Singleton is enum based Singleton. The
* is found in {@link EnumIvoryTower}. At first glance the code looks short and simple. However, you * example is found in {@link EnumIvoryTower}. At first glance the code looks short and simple.
* should be aware of the downsides including committing to implementation strategy, extending the * However, you should be aware of the downsides including committing to implementation strategy,
* enum class, serializability and restrictions to coding. These are extensively discussed in Stack * extending the enum class, serializability and restrictions to coding. These are extensively
* Overflow: * discussed in Stack Overflow:
* http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing * http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
* -a-singleton-with-javas-enum * -a-singleton-with-javas-enum</p>
* <p> *
* {@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on * <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 * demand. The downside is that it is very slow to access since the whole access method is
* synchronized. * synchronized.</p>
* <p> *
* Another Singleton implementation that is initialized on demand is found in * <p>Another Singleton implementation that is initialized on demand is found in
* {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than * {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than
* {@link ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but * {@link ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but
* only the method internals on specific conditions. * only the method internals on specific conditions.</p>
* <p> *
* Yet another way to implement thread safe lazily initialized Singleton can be found in * <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 * {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8
* API level to work. * API level to work.</p>
*/ */
public class App { public class App {

View File

@ -24,10 +24,10 @@
package com.iluwatar.singleton; 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 * <p>This implementation is thread safe, however adding any other method and its thread safety
* is developers responsibility. * is developers responsibility.</p>
*/ */
public enum EnumIvoryTower { public enum EnumIvoryTower {

View File

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

View File

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

View File

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

View File

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

View File

@ -24,14 +24,14 @@
package com.iluwatar.singleton; package com.iluwatar.singleton;
/** /**
* Date: 12/29/15 - 19:20 PM * Date: 12/29/15 - 19:20 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class EnumIvoryTowerTest extends SingletonTest<EnumIvoryTower> { 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() { public EnumIvoryTowerTest() {
super(() -> EnumIvoryTower.INSTANCE); super(() -> EnumIvoryTower.INSTANCE);

View File

@ -24,14 +24,15 @@
package com.iluwatar.singleton; package com.iluwatar.singleton;
/** /**
* Date: 12/29/15 - 19:22 PM * Date: 12/29/15 - 19:22 PM.
* *
* @author Jeroen Meulemeester * @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() { public InitializingOnDemandHolderIdiomTest() {
super(InitializingOnDemandHolderIdiom::getInstance); super(InitializingOnDemandHolderIdiom::getInstance);

View File

@ -24,14 +24,14 @@
package com.iluwatar.singleton; package com.iluwatar.singleton;
/** /**
* Date: 12/29/15 - 19:23 PM * Date: 12/29/15 - 19:23 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class IvoryTowerTest extends SingletonTest<IvoryTower> { 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() { public IvoryTowerTest() {
super(IvoryTower::getInstance); super(IvoryTower::getInstance);

View File

@ -23,8 +23,10 @@
package com.iluwatar.singleton; package com.iluwatar.singleton;
import org.junit.jupiter.api.Disabled; import static java.time.Duration.ofMillis;
import org.junit.jupiter.api.Test; 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.ArrayList;
import java.util.List; import java.util.List;
@ -34,19 +36,17 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.function.Supplier; import java.util.function.Supplier;
import static java.time.Duration.ofMillis; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTimeout;
/** /**
* 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 * <p>The first proves that multiple calls to the singleton getInstance object are the same when
* in the SAME thread. The second proves that multiple calls to the singleton getInstance object are * called in the SAME thread. The second proves that multiple calls to the singleton getInstance
* the same when called in the DIFFERENT thread. * 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 * @param <S> Supplier method generating singletons
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
* @author Richard Jones * @author Richard Jones
@ -54,12 +54,12 @@ import static org.junit.jupiter.api.Assertions.assertTimeout;
public abstract class SingletonTest<S> { public abstract class SingletonTest<S> {
/** /**
* The singleton's getInstance method * The singleton's getInstance method.
*/ */
private final Supplier<S> singletonInstanceMethod; 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 * @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 @Test
public void testMultipleCallsReturnTheSameObjectInSameThread() { 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 @Test
public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws Exception { public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws Exception {

View File

@ -23,34 +23,35 @@
package com.iluwatar.singleton; package com.iluwatar.singleton;
import org.junit.Test;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; 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 * @author Jeroen Meulemeester
*/ */
public class ThreadSafeDoubleCheckLockingTest extends SingletonTest<ThreadSafeDoubleCheckLocking> { 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() { public ThreadSafeDoubleCheckLockingTest() {
super(ThreadSafeDoubleCheckLocking::getInstance); super(ThreadSafeDoubleCheckLocking::getInstance);
} }
/** /**
* Test creating new instance by refection * Test creating new instance by refection.
*/ */
@Test(expected = InvocationTargetException.class) @Test(expected = InvocationTargetException.class)
public void testCreatingNewInstanceByRefection() throws Exception { public void testCreatingNewInstanceByRefection() throws Exception {
ThreadSafeDoubleCheckLocking instance1 = ThreadSafeDoubleCheckLocking.getInstance(); ThreadSafeDoubleCheckLocking instance1 = ThreadSafeDoubleCheckLocking.getInstance();
Constructor constructor = ThreadSafeDoubleCheckLocking.class.getDeclaredConstructor(); Constructor constructor = ThreadSafeDoubleCheckLocking.class.getDeclaredConstructor();
constructor.setAccessible(true); 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; package com.iluwatar.singleton;
/** /**
* Date: 12/29/15 - 19:26 PM * Date: 12/29/15 - 19:26 PM.
* *
* @author Jeroen Meulemeester * @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() { public ThreadSafeLazyLoadedIvoryTowerTest() {
super(ThreadSafeLazyLoadedIvoryTower::getInstance); super(ThreadSafeLazyLoadedIvoryTower::getInstance);

View File

@ -28,15 +28,15 @@ import org.slf4j.LoggerFactory;
/** /**
* *
* The Strategy pattern (also known as the policy pattern) is a software design pattern that enables * <p>The Strategy pattern (also known as the policy pattern) is a software design pattern that
* an algorithm's behavior to be selected at runtime. * enables an algorithm's behavior to be selected at runtime.</p>
* <p> *
* Before Java 8 the Strategies needed to be separate classes forcing the developer * <p>Before Java 8 the Strategies needed to be separate classes forcing the developer
* to write lots of boilerplate code. With modern Java it is easy to pass behavior * to write lots of boilerplate code. With modern Java it is easy to pass behavior
* with method references and lambdas making the code shorter and more readable. * with method references and lambdas making the code shorter and more readable.</p>
* <p> *
* In this example ({@link DragonSlayingStrategy}) encapsulates an algorithm. The containing object * <p>In this example ({@link DragonSlayingStrategy}) encapsulates an algorithm. The containing
* ({@link DragonSlayer}) can alter its behavior by changing its strategy. * object ({@link DragonSlayer}) can alter its behavior by changing its strategy.</p>
* *
*/ */
public class App { public class App {
@ -44,7 +44,7 @@ public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class); private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/** /**
* Program entry point * Program entry point.
* *
* @param args command line args * @param args command line args
*/ */

View File

@ -24,9 +24,7 @@
package com.iluwatar.strategy; package com.iluwatar.strategy;
/** /**
*
* DragonSlayer uses different strategies to slay the dragon. * DragonSlayer uses different strategies to slay the dragon.
*
*/ */
public class DragonSlayer { public class DragonSlayer {

View File

@ -24,9 +24,7 @@
package com.iluwatar.strategy; package com.iluwatar.strategy;
/** /**
*
* Strategy interface. * Strategy interface.
*
*/ */
@FunctionalInterface @FunctionalInterface
public interface DragonSlayingStrategy { public interface DragonSlayingStrategy {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
*
* Melee strategy. * Melee strategy.
*
*/ */
public class MeleeStrategy implements DragonSlayingStrategy { public class MeleeStrategy implements DragonSlayingStrategy {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
*
* Projectile strategy. * Projectile strategy.
*
*/ */
public class ProjectileStrategy implements DragonSlayingStrategy { public class ProjectileStrategy implements DragonSlayingStrategy {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
*
* Spell strategy. * Spell strategy.
*
*/ */
public class SpellStrategy implements DragonSlayingStrategy { public class SpellStrategy implements DragonSlayingStrategy {

View File

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

View File

@ -23,21 +23,21 @@
package com.iluwatar.strategy; package com.iluwatar.strategy;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/29/15 - 10:50 PM * Date: 12/29/15 - 10:50 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class DragonSlayerTest { public class DragonSlayerTest {
/** /**
* Verify if the dragon slayer uses the strategy during battle * Verify if the dragon slayer uses the strategy during battle.
*/ */
@Test @Test
public void testGoToBattle() { public void testGoToBattle() {
@ -50,7 +50,7 @@ public class DragonSlayerTest {
} }
/** /**
* Verify if the dragon slayer uses the new strategy during battle after a change of strategy * Verify if the dragon slayer uses the new strategy during battle after a change of strategy.
*/ */
@Test @Test
public void testChangeStrategy() { public void testChangeStrategy() {

View File

@ -23,45 +23,48 @@
package com.iluwatar.strategy; package com.iluwatar.strategy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase; import ch.qos.logback.core.AppenderBase;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
* Date: 12/29/15 - 10:58 PM * Date: 12/29/15 - 10:58 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class DragonSlayingStrategyTest { public class DragonSlayingStrategyTest {
/** /**
* Assembles test parameters.
*
* @return The test parameters for each cycle * @return The test parameters for each cycle
*/ */
static Collection<Object[]> dataProvider() { static Collection<Object[]> dataProvider() {
return List.of( return List.of(
new Object[]{ new Object[]{
new MeleeStrategy(), new MeleeStrategy(),
"With your Excalibur you sever the dragon's head!" "With your Excalibur you sever the dragon's head!"
}, },
new Object[]{ new Object[]{
new ProjectileStrategy(), new ProjectileStrategy(),
"You shoot the dragon with the magical crossbow and it falls dead on the ground!" "You shoot the dragon with the magical crossbow and it falls dead on the ground!"
}, },
new Object[]{ new Object[]{
new SpellStrategy(), new SpellStrategy(),
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!" "You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"
} }
); );
} }
@ -79,7 +82,7 @@ public class DragonSlayingStrategyTest {
/** /**
* Test if executing the strategy gives the correct response * Test if executing the strategy gives the correct response.
*/ */
@ParameterizedTest @ParameterizedTest
@MethodSource("dataProvider") @MethodSource("dataProvider")

View File

@ -24,19 +24,18 @@
package com.iluwatar.visitor; package com.iluwatar.visitor;
/** /**
* * <p>Visitor pattern defines mechanism to apply operations on nodes in hierarchy. New operations
* Visitor pattern defines mechanism to apply operations on nodes in hierarchy. New operations can * can be added without altering the node interface.</p>
* be added without altering the node interface. *
* <p> * <p>In this example there is a unit hierarchy beginning from {@link Commander}. This hierarchy is
* In this example there is a unit hierarchy beginning from {@link Commander}. This hierarchy is
* traversed by visitors. {@link SoldierVisitor} applies its operation on {@link Soldier}s, * traversed by visitors. {@link SoldierVisitor} applies its operation on {@link Soldier}s,
* {@link SergeantVisitor} on {@link Sergeant}s and so on. * {@link SergeantVisitor} on {@link Sergeant}s and so on.</p>
* *
*/ */
public class App { public class App {
/** /**
* Program entry point * Program entry point.
* *
* @param args command line args * @param args command line args
*/ */

View File

@ -24,9 +24,7 @@
package com.iluwatar.visitor; package com.iluwatar.visitor;
/** /**
* * Commander.
* Commander
*
*/ */
public class Commander extends Unit { public class Commander extends Unit {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * CommanderVisitor.
* CommanderVisitor
*
*/ */
public class CommanderVisitor implements UnitVisitor { public class CommanderVisitor implements UnitVisitor {

View File

@ -24,9 +24,7 @@
package com.iluwatar.visitor; package com.iluwatar.visitor;
/** /**
* * Sergeant.
* Sergeant
*
*/ */
public class Sergeant extends Unit { public class Sergeant extends Unit {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * SergeantVisitor.
* SergeantVisitor
*
*/ */
public class SergeantVisitor implements UnitVisitor { public class SergeantVisitor implements UnitVisitor {

View File

@ -24,9 +24,7 @@
package com.iluwatar.visitor; package com.iluwatar.visitor;
/** /**
* * Soldier.
* Soldier
*
*/ */
public class Soldier extends Unit { public class Soldier extends Unit {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * SoldierVisitor.
* SoldierVisitor
*
*/ */
public class SoldierVisitor implements UnitVisitor { public class SoldierVisitor implements UnitVisitor {

View File

@ -24,9 +24,7 @@
package com.iluwatar.visitor; package com.iluwatar.visitor;
/** /**
*
* Interface for the nodes in hierarchy. * Interface for the nodes in hierarchy.
*
*/ */
public abstract class Unit { public abstract class Unit {
@ -37,7 +35,7 @@ public abstract class Unit {
} }
/** /**
* Accept visitor * Accept visitor.
*/ */
public void accept(UnitVisitor visitor) { public void accept(UnitVisitor visitor) {
for (var child : children) { for (var child : children) {

View File

@ -24,9 +24,7 @@
package com.iluwatar.visitor; package com.iluwatar.visitor;
/** /**
*
* Visitor interface. * Visitor interface.
*
*/ */
public interface UnitVisitor { public interface UnitVisitor {

View File

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

View File

@ -27,14 +27,14 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
/** /**
* Date: 12/30/15 - 19:45 PM * Date: 12/30/15 - 19:45 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class CommanderTest extends UnitTest<Commander> { public class CommanderTest extends UnitTest<Commander> {
/** /**
* Create a new test instance for the given {@link Commander} * Create a new test instance for the given {@link Commander}.
*/ */
public CommanderTest() { public CommanderTest() {
super(Commander::new); super(Commander::new);

View File

@ -26,14 +26,14 @@ package com.iluwatar.visitor;
import java.util.Optional; import java.util.Optional;
/** /**
* Date: 12/30/15 - 18:43 PM * Date: 12/30/15 - 18:43 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class CommanderVisitorTest extends VisitorTest<CommanderVisitor> { public class CommanderVisitorTest extends VisitorTest<CommanderVisitor> {
/** /**
* Create a new test instance for the given visitor * Create a new test instance for the given visitor.
*/ */
public CommanderVisitorTest() { public CommanderVisitorTest() {
super( super(

View File

@ -27,14 +27,14 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
/** /**
* Date: 12/30/15 - 19:45 PM * Date: 12/30/15 - 19:45 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class SergeantTest extends UnitTest<Sergeant> { public class SergeantTest extends UnitTest<Sergeant> {
/** /**
* Create a new test instance for the given {@link Sergeant} * Create a new test instance for the given {@link Sergeant}.
*/ */
public SergeantTest() { public SergeantTest() {
super(Sergeant::new); super(Sergeant::new);

View File

@ -26,14 +26,14 @@ package com.iluwatar.visitor;
import java.util.Optional; import java.util.Optional;
/** /**
* Date: 12/30/15 - 18:36 PM * Date: 12/30/15 - 18:36 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class SergeantVisitorTest extends VisitorTest<SergeantVisitor> { public class SergeantVisitorTest extends VisitorTest<SergeantVisitor> {
/** /**
* Create a new test instance for the given visitor * Create a new test instance for the given visitor.
*/ */
public SergeantVisitorTest() { public SergeantVisitorTest() {
super( super(

View File

@ -27,14 +27,14 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
/** /**
* Date: 12/30/15 - 19:45 PM * Date: 12/30/15 - 19:45 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class SoldierTest extends UnitTest<Soldier> { public class SoldierTest extends UnitTest<Soldier> {
/** /**
* Create a new test instance for the given {@link Soldier} * Create a new test instance for the given {@link Soldier}.
*/ */
public SoldierTest() { public SoldierTest() {
super(Soldier::new); super(Soldier::new);

View File

@ -26,14 +26,14 @@ package com.iluwatar.visitor;
import java.util.Optional; import java.util.Optional;
/** /**
* Date: 12/30/15 - 18:59 PM * Date: 12/30/15 - 18:59 PM.
* *
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
*/ */
public class SoldierVisitorTest extends VisitorTest<SoldierVisitor> { public class SoldierVisitorTest extends VisitorTest<SoldierVisitor> {
/** /**
* Create a new test instance for the given visitor * Create a new test instance for the given visitor.
*/ */
public SoldierVisitorTest() { public SoldierVisitorTest() {
super( super(

View File

@ -23,18 +23,18 @@
package com.iluwatar.visitor; package com.iluwatar.visitor;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.function.Function;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import java.util.Arrays;
import java.util.function.Function;
import org.junit.jupiter.api.Test;
/** /**
* Date: 12/30/15 - 18:59 PM * Date: 12/30/15 - 18:59 PM.
* Test related to Units * Test related to Units
* @param <U> Type of Unit * @param <U> Type of Unit
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
@ -42,12 +42,12 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
public abstract class UnitTest<U extends Unit> { public abstract class UnitTest<U extends Unit> {
/** /**
* Factory to create new instances of the tested unit * Factory to create new instances of the tested unit.
*/ */
private final Function<Unit[], U> factory; private final Function<Unit[], U> factory;
/** /**
* Create a new test instance for the given unit type {@link U} * Create a new test instance for the given unit type {@link U}.
* *
* @param factory Factory to create new instances of the tested unit * @param factory Factory to create new instances of the tested unit
*/ */
@ -74,7 +74,7 @@ public abstract class UnitTest<U extends Unit> {
} }
/** /**
* Verify if the correct visit method is called on the mock, depending on the tested instance * Verify if the correct visit method is called on the mock, depending on the tested instance.
* *
* @param unit The tested unit instance * @param unit The tested unit instance
* @param mockedVisitor The mocked {@link UnitVisitor} who should have gotten a visit by the unit * @param mockedVisitor The mocked {@link UnitVisitor} who should have gotten a visit by the unit

View File

@ -23,6 +23,8 @@
package com.iluwatar.visitor; package com.iluwatar.visitor;
import static org.junit.jupiter.api.Assertions.assertEquals;
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase; import ch.qos.logback.core.AppenderBase;
@ -35,10 +37,8 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
* Date: 12/30/15 - 18:59 PM * Date: 12/30/15 - 18:59 PM.
* Test case for Visitor Pattern * Test case for Visitor Pattern
* @param <V> Type of UnitVisitor * @param <V> Type of UnitVisitor
* @author Jeroen Meulemeester * @author Jeroen Meulemeester
@ -58,34 +58,36 @@ public abstract class VisitorTest<V extends UnitVisitor> {
} }
/** /**
* The tested visitor instance * The tested visitor instance.
*/ */
private final V visitor; private final V visitor;
/** /**
* The optional expected response when being visited by a commander * The optional expected response when being visited by a commander.
*/ */
private final Optional<String> commanderResponse; private final Optional<String> commanderResponse;
/** /**
* The optional expected response when being visited by a sergeant * The optional expected response when being visited by a sergeant.
*/ */
private final Optional<String> sergeantResponse; private final Optional<String> sergeantResponse;
/** /**
* The optional expected response when being visited by a soldier * The optional expected response when being visited by a soldier.
*/ */
private final Optional<String> soldierResponse; private final Optional<String> soldierResponse;
/** /**
* Create a new test instance for the given visitor * Create a new test instance for the given visitor.
* *
* @param commanderResponse The optional expected response when being visited by a commander * @param commanderResponse The optional expected response when being visited by a commander
* @param sergeantResponse The optional expected response when being visited by a sergeant * @param sergeantResponse The optional expected response when being visited by a sergeant
* @param soldierResponse The optional expected response when being visited by a soldier * @param soldierResponse The optional expected response when being visited by a soldier
*/ */
public VisitorTest(final V visitor, final Optional<String> commanderResponse, public VisitorTest(final V visitor,
final Optional<String> sergeantResponse, final Optional<String> soldierResponse) { final Optional<String> commanderResponse,
final Optional<String> sergeantResponse,
final Optional<String> soldierResponse) {
this.visitor = visitor; this.visitor = visitor;
this.commanderResponse = commanderResponse; this.commanderResponse = commanderResponse;