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,29 +23,32 @@
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() {
@ -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
* can be added without altering the node interface.</p>
* *
* Visitor pattern defines mechanism to apply operations on nodes in hierarchy. New operations can * <p>In this example there is a unit hierarchy beginning from {@link Commander}. This hierarchy is
* be added without altering the node interface.
* <p>
* 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;