* fix checkstlye errors - visitor pattern * fix checkstlye errors - strategy pattern * fix checkstlye errors - singleton pattern
This commit is contained in:
committed by
Ilkka Seppälä
parent
1eb1961f1b
commit
3b1a28149b
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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);
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.strategy;
|
package com.iluwatar.strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Strategy interface.
|
* Strategy interface.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface DragonSlayingStrategy {
|
public interface DragonSlayingStrategy {
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.visitor;
|
package com.iluwatar.visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Commander.
|
||||||
* Commander
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class Commander extends Unit {
|
public class Commander extends Unit {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.visitor;
|
package com.iluwatar.visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Sergeant.
|
||||||
* Sergeant
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class Sergeant extends Unit {
|
public class Sergeant extends Unit {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.visitor;
|
package com.iluwatar.visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Soldier.
|
||||||
* Soldier
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class Soldier extends Unit {
|
public class Soldier extends Unit {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.visitor;
|
package com.iluwatar.visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Visitor interface.
|
* Visitor interface.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface UnitVisitor {
|
public interface UnitVisitor {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user