Resolves checkstyle errors for delegation dependency-injection dirty-flag double-buffer double-checked-locking double-dispatch (#1068)

* Reduces checkstyle errors in delegation

* Reduces checkstyle errors in dependency-injection

* Reduces checkstyle errors in dirty-flag

* Reduces checkstyle errors in double-buffer

* Reduces checkstyle errors in double-checked-locking

* Reduces checkstyle errors in double-dispatch
This commit is contained in:
Anurag Agarwal 2019-11-10 23:01:20 +05:30 committed by Ilkka Seppälä
parent 01e489c77b
commit f2c91eb836
35 changed files with 154 additions and 215 deletions

View File

@ -28,23 +28,25 @@ import com.iluwatar.delegation.simple.printers.EpsonPrinter;
import com.iluwatar.delegation.simple.printers.HpPrinter; import com.iluwatar.delegation.simple.printers.HpPrinter;
/** /**
* The delegate pattern provides a mechanism to abstract away the implementation and control of the desired action. * The delegate pattern provides a mechanism to abstract away the implementation and control of the
* The class being called in this case {@link PrinterController} is not responsible for the actual desired action, * desired action. The class being called in this case {@link PrinterController} is not responsible
* but is actually delegated to a helper class either {@link CanonPrinter}, {@link EpsonPrinter} or {@link HpPrinter}. * for the actual desired action, but is actually delegated to a helper class either {@link
* The consumer does not have or require knowledge of the actual class carrying out the action, only the * CanonPrinter}, {@link EpsonPrinter} or {@link HpPrinter}. The consumer does not have or require
* container on which they are calling. * knowledge of the actual class carrying out the action, only the container on which they are
* calling.
* *
* In this example the delegates are {@link EpsonPrinter}, {@link HpPrinter} and {@link CanonPrinter} they all implement * <p>In this example the delegates are {@link EpsonPrinter}, {@link HpPrinter} and {@link
* {@link Printer}. The {@link PrinterController} class also implements {@link Printer}. However neither provide the * CanonPrinter} they all implement {@link Printer}. The {@link PrinterController} class also
* functionality of {@link Printer} by printing to the screen, they actually call upon the instance of {@link Printer} * implements {@link Printer}. However neither provide the functionality of {@link Printer} by
* that they were instantiated with. Therefore delegating the behaviour to another class. * printing to the screen, they actually call upon the instance of {@link Printer} that they were
* instantiated with. Therefore delegating the behaviour to another class.
*/ */
public class App { public class App {
private static final String MESSAGE_TO_PRINT = "hello world"; private static final String MESSAGE_TO_PRINT = "hello world";
/** /**
* Program entry point * Program entry point.
* *
* @param args command line args * @param args command line args
*/ */

View File

@ -38,7 +38,8 @@ public interface Printer {
/** /**
* Method that takes a String to print to the screen. This will be implemented on both the * Method that takes a String to print to the screen. This will be implemented on both the
* controller and the delegate allowing the controller to call the same method on the delegate class. * controller and the delegate allowing the controller to call the same method on the delegate
* class.
* *
* @param message to be printed to the screen * @param message to be printed to the screen
*/ */

View File

@ -24,10 +24,10 @@
package com.iluwatar.delegation.simple; package com.iluwatar.delegation.simple;
/** /**
* Delegator Class to delegate the implementation of the Printer. * Delegator Class to delegate the implementation of the Printer. This ensures two things: - when
* This ensures two things: * the actual implementation of the Printer class changes the delegation will still be operational -
* - when the actual implementation of the Printer class changes the delegation will still be operational * the actual benefit is observed when there are more than one implementors and they share a
* - the actual benefit is observed when there are more than one implementors and they share a delegation control * delegation control
*/ */
public class PrinterController implements Printer { public class PrinterController implements Printer {
@ -38,10 +38,10 @@ public class PrinterController implements Printer {
} }
/** /**
* This method is implemented from {@link Printer} however instead on providing an * This method is implemented from {@link Printer} however instead on providing an implementation,
* implementation, it instead calls upon the class passed through the constructor. This is the delegate, * it instead calls upon the class passed through the constructor. This is the delegate, hence the
* hence the pattern. Therefore meaning that the caller does not care of the implementing class only the owning * pattern. Therefore meaning that the caller does not care of the implementing class only the
* controller. * owning controller.
* *
* @param message to be printed to the screen * @param message to be printed to the screen
*/ */

View File

@ -28,8 +28,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* Specialised Implementation of {@link Printer} for a Canon Printer, in * Specialised Implementation of {@link Printer} for a Canon Printer, in this case the message to be
* this case the message to be printed is appended to "Canon Printer : " * printed is appended to "Canon Printer : ".
* *
* @see Printer * @see Printer
*/ */

View File

@ -28,8 +28,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* Specialised Implementation of {@link Printer} for a Epson Printer, in * Specialised Implementation of {@link Printer} for a Epson Printer, in this case the message to be
* this case the message to be printed is appended to "Epson Printer : " * printed is appended to "Epson Printer : ".
* *
* @see Printer * @see Printer
*/ */

View File

@ -28,8 +28,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* Specialised Implementation of {@link Printer} for a HP Printer, in * Specialised Implementation of {@link Printer} for a HP Printer, in this case the message to be
* this case the message to be printed is appended to "HP Printer : " * printed is appended to "HP Printer : ".
* *
* @see Printer * @see Printer
*/ */

View File

@ -23,30 +23,6 @@
package com.iluwatar.dependency.injection; package com.iluwatar.dependency.injection;
/**
* The MIT License
* Copyright (c) 2014-2017 Ilkka Seppälä
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* <p>
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/** /**
* AdvancedSorceress implements inversion of control. It depends on abstraction that can be injected * AdvancedSorceress implements inversion of control. It depends on abstraction that can be injected
* through its setter. * through its setter.

View File

@ -24,10 +24,8 @@
package com.iluwatar.dependency.injection; package com.iluwatar.dependency.injection;
/** /**
*
* AdvancedWizard implements inversion of control. It depends on abstraction that can be injected * AdvancedWizard implements inversion of control. It depends on abstraction that can be injected
* through its constructor. * through its constructor.
*
*/ */
public class AdvancedWizard implements Wizard { public class AdvancedWizard implements Wizard {

View File

@ -31,25 +31,26 @@ import com.google.inject.Injector;
* implements so called inversion of control principle. Inversion of control has two specific rules: * implements so called inversion of control principle. Inversion of control has two specific rules:
* - High-level modules should not depend on low-level modules. Both should depend on abstractions. * - High-level modules should not depend on low-level modules. Both should depend on abstractions.
* - Abstractions should not depend on details. Details should depend on abstractions. * - Abstractions should not depend on details. Details should depend on abstractions.
* <p> *
* In this example we show you three different wizards. The first one ({@link SimpleWizard}) is a * <p>In this example we show you three different wizards. The first one ({@link SimpleWizard}) is
* naive implementation violating the inversion of control principle. It depends directly on a * a naive implementation violating the inversion of control principle. It depends directly on a
* concrete implementation which cannot be changed. * concrete implementation which cannot be changed.
* <p> *
* The second and third wizards({@link AdvancedWizard} and {@link AdvancedSorceress}) are more flexible. * <p>The second and third wizards({@link AdvancedWizard} and {@link AdvancedSorceress}) are more
* They do not depend on any concrete implementation but abstraction. They utilizes Dependency Injection * flexible. They do not depend on any concrete implementation but abstraction. They utilizes
* pattern allowing their {@link Tobacco} dependency to be injected through constructor ({@link AdvancedWizard}) * Dependency Injection pattern allowing their {@link Tobacco} dependency to be injected through
* or setter ({@link AdvancedSorceress}). This way, handling the dependency is no longer the wizard's * constructor ({@link AdvancedWizard}) or setter ({@link AdvancedSorceress}). This way, handling
* responsibility. It is resolved outside the wizard class. * the dependency is no longer the wizard's responsibility. It is resolved outside the wizard
* <p> * class.
* The fourth example takes the pattern a step further. It uses Guice framework for Dependency *
* <p>The fourth example takes the pattern a step further. It uses Guice framework for Dependency
* Injection. {@link TobaccoModule} binds a concrete implementation to abstraction. Injector is then * Injection. {@link TobaccoModule} binds a concrete implementation to abstraction. Injector is then
* used to create {@link GuiceWizard} object with correct dependencies. * used to create {@link GuiceWizard} object with correct dependencies.
*/ */
public class App { public class App {
/** /**
* Program entry point * Program entry point.
* *
* @param args command line args * @param args command line args
*/ */

View File

@ -26,10 +26,8 @@ package com.iluwatar.dependency.injection;
import javax.inject.Inject; import javax.inject.Inject;
/** /**
*
* GuiceWizard implements inversion of control. Its dependencies are injected through its * GuiceWizard implements inversion of control. Its dependencies are injected through its
* constructor by Guice framework. * constructor by Guice framework.
*
*/ */
public class GuiceWizard implements Wizard { public class GuiceWizard implements Wizard {

View File

@ -24,9 +24,7 @@
package com.iluwatar.dependency.injection; package com.iluwatar.dependency.injection;
/** /**
* * OldTobyTobacco concrete {@link Tobacco} implementation.
* OldTobyTobacco concrete {@link Tobacco} implementation
*
*/ */
public class OldTobyTobacco extends Tobacco { public class OldTobyTobacco extends Tobacco {
} }

View File

@ -24,9 +24,7 @@
package com.iluwatar.dependency.injection; package com.iluwatar.dependency.injection;
/** /**
* * RivendellTobacco concrete {@link Tobacco} implementation.
* RivendellTobacco concrete {@link Tobacco} implementation
*
*/ */
public class RivendellTobacco extends Tobacco { public class RivendellTobacco extends Tobacco {
} }

View File

@ -24,9 +24,7 @@
package com.iluwatar.dependency.injection; package com.iluwatar.dependency.injection;
/** /**
* * SecondBreakfastTobacco concrete {@link Tobacco} implementation.
* SecondBreakfastTobacco concrete {@link Tobacco} implementation
*
*/ */
public class SecondBreakfastTobacco extends Tobacco { public class SecondBreakfastTobacco extends Tobacco {
} }

View File

@ -24,10 +24,8 @@
package com.iluwatar.dependency.injection; package com.iluwatar.dependency.injection;
/** /**
*
* Naive Wizard implementation violating the inversion of control principle. It should depend on * Naive Wizard implementation violating the inversion of control principle. It should depend on
* abstraction instead. * abstraction instead.
*
*/ */
public class SimpleWizard implements Wizard { public class SimpleWizard implements Wizard {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * Tobacco abstraction.
* Tobacco abstraction
*
*/ */
public abstract class Tobacco { public abstract class Tobacco {

View File

@ -26,9 +26,7 @@ package com.iluwatar.dependency.injection;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
/** /**
*
* Guice module for binding certain concrete {@link Tobacco} implementation. * Guice module for binding certain concrete {@link Tobacco} implementation.
*
*/ */
public class TobaccoModule extends AbstractModule { public class TobaccoModule extends AbstractModule {

View File

@ -24,9 +24,7 @@
package com.iluwatar.dependency.injection; package com.iluwatar.dependency.injection;
/** /**
* * Wizard interface.
* Wizard interface
*
*/ */
public interface Wizard { public interface Wizard {

View File

@ -23,45 +23,49 @@
package com.iluwatar.dirtyflag; package com.iluwatar.dirtyflag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* This application demonstrates the <b>Dirty Flag</b> pattern. The dirty flag behavioral pattern
* allows you to avoid expensive operations that would just need to be done again anyway. This is a
* simple pattern that really just explains how to add a bool value to your class that you can set
* anytime a property changes. This will let your class know that any results it may have previously
* calculated will need to be calculated again when theyre requested. Once the results are
* re-calculated, then the bool value can be cleared.
* *
* This application demonstrates the <b>Dirty Flag</b> pattern. The dirty flag behavioral pattern allows you to avoid * <p>There are some points that need to be considered before diving into using this pattern:-
* expensive operations that would just need to be done again anyway. This is a simple pattern that really just explains * there are some things youll need to consider:- (1) Do you need it? This design pattern works
* how to add a bool value to your class that you can set anytime a property changes. This will let your class know that * well when the results to be calculated are difficult or resource intensive to compute. You want
* any results it may have previously calculated will need to be calculated again when theyre requested. Once the * to save them. You also dont want to be calculating them several times in a row when only the
* results are re-calculated, then the bool value can be cleared. * last one counts. (2) When do you set the dirty flag? Make sure that you set the dirty flag within
* * the class itself whenever an important property changes. This property should affect the result
* There are some points that need to be considered before diving into using this pattern:- there are some things youll * of the calculated result and by changing the property, that makes the last result invalid. (3)
* need to consider:- (1) Do you need it? This design pattern works well when the results to be calculated are difficult * When do you clear the dirty flag? It might seem obvious that the dirty flag should be cleared
* or resource intensive to compute. You want to save them. You also dont want to be calculating them several times in * whenever the result is calculated with up-to-date information but there are other times when you
* a row when only the last one counts. (2) When do you set the dirty flag? Make sure that you set the dirty flag within * might want to clear the flag.
* the class itself whenever an important property changes. This property should affect the result of the calculated
* result and by changing the property, that makes the last result invalid. (3) When do you clear the dirty flag? It
* might seem obvious that the dirty flag should be cleared whenever the result is calculated with up-to-date
* information but there are other times when you might want to clear the flag.
* *
* In this example, the {@link DataFetcher} holds the <i>dirty flag</i>. It fetches and re-fetches from <i>world.txt</i> * <p>In this example, the {@link DataFetcher} holds the <i>dirty flag</i>. It fetches and
* when needed. {@link World} mainly serves the data to the front-end. * re-fetches from <i>world.txt</i> when needed. {@link World} mainly serves the data to the
* front-end.
*/ */
public class App { public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class); private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/** /**
* Program execution point * Program execution point.
*/ */
public void run() { public void run() {
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(new Runnable() { executorService.scheduleAtFixedRate(new Runnable() {
final World world = new World(); final World world = new World();
@Override @Override
public void run() { public void run() {
List<String> countries = world.fetch(); List<String> countries = world.fetch();
@ -74,10 +78,9 @@ public class App {
} }
/** /**
* Program entry point * Program entry point.
* *
* @param args * @param args command line args
* command line args
*/ */
public static void main(String[] args) { public static void main(String[] args) {
App app = new App(); App app = new App();

View File

@ -23,22 +23,19 @@
package com.iluwatar.dirtyflag; package com.iluwatar.dirtyflag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.crypto.Data;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* A mock database manager -- Fetches data from a raw file. * A mock database manager -- Fetches data from a raw file.
*
* @author swaisuan
* *
* @author swaisuan
*/ */
public class DataFetcher { public class DataFetcher {
@ -61,7 +58,7 @@ public class DataFetcher {
/** /**
* Fetches data/content from raw file. * Fetches data/content from raw file.
* *
* @return List of strings * @return List of strings
*/ */
public List<String> fetch() { public List<String> fetch() {

View File

@ -27,11 +27,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
*
* A middle-layer app that calls/passes along data from the back-end. * A middle-layer app that calls/passes along data from the back-end.
*
* @author swaisuan
* *
* @author swaisuan
*/ */
public class World { public class World {
@ -44,9 +42,8 @@ public class World {
} }
/** /**
*
* Calls {@link DataFetcher} to fetch data from back-end. * Calls {@link DataFetcher} to fetch data from back-end.
* *
* @return List of strings * @return List of strings
*/ */
public List<String> fetch() { public List<String> fetch() {

View File

@ -23,21 +23,19 @@
package com.iluwatar.doublebuffer; package com.iluwatar.doublebuffer;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/** /**
* Double buffering is a term used to describe a device that has two buffers. * Double buffering is a term used to describe a device that has two buffers. The usage of multiple
* The usage of multiple buffers increases the overall throughput of a device * buffers increases the overall throughput of a device and helps prevents bottlenecks. This example
* and helps prevents bottlenecks. This example shows using double buffer pattern * shows using double buffer pattern on graphics. It is used to show one image or frame while a
* on graphics. It is used to show one image or frame while a separate frame * separate frame is being buffered to be shown next. This method makes animations and games look
* is being buffered to be shown next. This method makes animations and games * more realistic than the same done in a single buffer mode.
* look more realistic than the same done in a single buffer mode.
*/ */
public class App { public class App {
@ -45,10 +43,11 @@ public class App {
/** /**
* Program main entry point. * Program main entry point.
*
* @param args runtime arguments * @param args runtime arguments
*/ */
public static void main(String[] args) { public static void main(String[] args) {
var scene = new Scene(); final var scene = new Scene();
List<Pair<Integer, Integer>> drawPixels = new ArrayList<>(); List<Pair<Integer, Integer>> drawPixels = new ArrayList<>();
Pair<Integer, Integer> pixel1 = new MutablePair<>(1, 1); Pair<Integer, Integer> pixel1 = new MutablePair<>(1, 1);
Pair<Integer, Integer> pixel2 = new MutablePair<>(5, 6); Pair<Integer, Integer> pixel2 = new MutablePair<>(5, 6);

View File

@ -30,6 +30,7 @@ public interface Buffer {
/** /**
* Clear the pixel in (x, y). * Clear the pixel in (x, y).
*
* @param x X coordinate * @param x X coordinate
* @param y Y coordinate * @param y Y coordinate
*/ */
@ -37,6 +38,7 @@ public interface Buffer {
/** /**
* Draw the pixel in (x, y). * Draw the pixel in (x, y).
*
* @param x X coordinate * @param x X coordinate
* @param y Y coordinate * @param y Y coordinate
*/ */
@ -49,6 +51,7 @@ public interface Buffer {
/** /**
* Get all the pixels. * Get all the pixels.
*
* @return pixel list * @return pixel list
*/ */
Pixel[] getPixels(); Pixel[] getPixels();

View File

@ -23,9 +23,6 @@
package com.iluwatar.doublebuffer; package com.iluwatar.doublebuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* FrameBuffer implementation class. * FrameBuffer implementation class.
*/ */

View File

@ -23,12 +23,11 @@
package com.iluwatar.doublebuffer; package com.iluwatar.doublebuffer;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.List;
/** /**
* Scene class. Render the output frame. * Scene class. Render the output frame.
*/ */
@ -55,6 +54,7 @@ public class Scene {
/** /**
* Draw the next frame. * Draw the next frame.
*
* @param coordinateList list of pixels of which the color should be black * @param coordinateList list of pixels of which the color should be black
*/ */
public void draw(List<Pair<Integer, Integer>> coordinateList) { public void draw(List<Pair<Integer, Integer>> coordinateList) {

View File

@ -23,32 +23,30 @@
package com.iluwatar.doublechecked.locking; package com.iluwatar.doublechecked.locking;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
*
* Double Checked Locking is a concurrency design pattern used to reduce the overhead of acquiring a * Double Checked Locking is a concurrency design pattern used to reduce the overhead of acquiring a
* lock by first testing the locking criterion (the "lock hint") without actually acquiring the * lock by first testing the locking criterion (the "lock hint") without actually acquiring the
* lock. Only if the locking criterion check indicates that locking is required does the actual * lock. Only if the locking criterion check indicates that locking is required does the actual
* locking logic proceed. * locking logic proceed.
* <p> *
* In {@link Inventory} we store the items with a given size. However, we do not store more items * <p>In {@link Inventory} we store the items with a given size. However, we do not store more
* than the inventory size. To address concurrent access problems we use double checked locking to * items than the inventory size. To address concurrent access problems we use double checked
* add item to inventory. In this method, the thread which gets the lock first adds the item. * locking to add item to inventory. In this method, the thread which gets the lock first adds the
* * item.
*/ */
public class App { 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
*/ */
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -23,19 +23,16 @@
package com.iluwatar.doublechecked.locking; package com.iluwatar.doublechecked.locking;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* * Inventory.
* Inventory
*
*/ */
public class Inventory { public class Inventory {
@ -46,7 +43,7 @@ public class Inventory {
private final Lock lock; private final Lock lock;
/** /**
* Constructor * Constructor.
*/ */
public Inventory(int inventorySize) { public Inventory(int inventorySize) {
this.inventorySize = inventorySize; this.inventorySize = inventorySize;
@ -55,7 +52,7 @@ public class Inventory {
} }
/** /**
* Add item * Add item.
*/ */
public boolean addItem(Item item) { public boolean addItem(Item item) {
if (items.size() < inventorySize) { if (items.size() < inventorySize) {
@ -63,7 +60,8 @@ public class Inventory {
try { try {
if (items.size() < inventorySize) { if (items.size() < inventorySize) {
items.add(item); items.add(item);
LOGGER.info("{}: items.size()={}, inventorySize={}", Thread.currentThread(), items.size(), inventorySize); LOGGER.info("{}: items.size()={}, inventorySize={}", Thread.currentThread(), items
.size(), inventorySize);
return true; return true;
} }
} finally { } finally {
@ -74,7 +72,7 @@ public class Inventory {
} }
/** /**
* Get all the items in the inventory * Get all the items in the inventory.
* *
* @return All the items of the inventory, as an unmodifiable list * @return All the items of the inventory, as an unmodifiable list
*/ */

View File

@ -24,9 +24,7 @@
package com.iluwatar.doublechecked.locking; package com.iluwatar.doublechecked.locking;
/** /**
* * Item.
* Item
*
*/ */
public class Item { public class Item {
} }

View File

@ -23,46 +23,45 @@
package com.iluwatar.doubledispatch; package com.iluwatar.doubledispatch;
import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.List;
/** /**
* * When a message with a parameter is sent to an object, the resultant behaviour is defined by the
* When a message with a parameter is sent to an object, the resultant behaviour is defined by the implementation of * implementation of that method in the receiver. Sometimes the behaviour must also be determined by
* that method in the receiver. Sometimes the behaviour must also be determined by the type of the parameter. * the type of the parameter.
* <p>
* One way to implement this would be to create multiple instanceof-checks for the methods parameter. However, this
* creates a maintenance issue. When new types are added we would also need to change the method's implementation and
* add a new instanceof-check. This violates the single responsibility principle - a class should have only one reason
* to change.
* <p>
* Instead of the instanceof-checks a better way is to make another virtual call on the parameter object. This way new
* functionality can be easily added without the need to modify existing implementation (open-closed principle).
* <p>
* In this example we have hierarchy of objects ({@link GameObject}) that can collide to each other. Each object has its
* own coordinates which are checked against the other objects' coordinates. If there is an overlap, then the objects
* collide utilizing the Double Dispatch pattern.
* *
* <p>One way to implement this would be to create multiple instanceof-checks for the methods
* parameter. However, this creates a maintenance issue. When new types are added we would also need
* to change the method's implementation and add a new instanceof-check. This violates the single
* responsibility principle - a class should have only one reason to change.
*
* <p>Instead of the instanceof-checks a better way is to make another virtual call on the
* parameter object. This way new functionality can be easily added without the need to modify
* existing implementation (open-closed principle).
*
* <p>In this example we have hierarchy of objects ({@link GameObject}) that can collide to each
* other. Each object has its own coordinates which are checked against the other objects'
* coordinates. If there is an overlap, then the objects collide utilizing the Double Dispatch
* pattern.
*/ */
public class App { 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 * @param args command line args
* command line args
*/ */
public static void main(String[] args) { public static void main(String[] args) {
// initialize game objects and print their status // initialize game objects and print their status
List<GameObject> objects = List.of( List<GameObject> objects = List.of(
new FlamingAsteroid(0, 0, 5, 5), new FlamingAsteroid(0, 0, 5, 5),
new SpaceStationMir(1, 1, 2, 2), new SpaceStationMir(1, 1, 2, 2),
new Meteoroid(10, 10, 15, 15), new Meteoroid(10, 10, 15, 15),
new SpaceStationIss(12, 12, 14, 14)); new SpaceStationIss(12, 12, 14, 14));
objects.stream().forEach(o -> LOGGER.info(o.toString())); objects.stream().forEach(o -> LOGGER.info(o.toString()));
LOGGER.info(""); LOGGER.info("");

View File

@ -24,9 +24,7 @@
package com.iluwatar.doubledispatch; package com.iluwatar.doubledispatch;
/** /**
* * Flaming asteroid game object.
* Flaming asteroid game object
*
*/ */
public class FlamingAsteroid extends Meteoroid { public class FlamingAsteroid extends Meteoroid {

View File

@ -24,9 +24,7 @@
package com.iluwatar.doubledispatch; package com.iluwatar.doubledispatch;
/** /**
*
* Game objects have coordinates and some other status information. * Game objects have coordinates and some other status information.
*
*/ */
public abstract class GameObject extends Rectangle { public abstract class GameObject extends Rectangle {

View File

@ -23,15 +23,12 @@
package com.iluwatar.doubledispatch; package com.iluwatar.doubledispatch;
import com.iluwatar.doubledispatch.constants.AppConstants;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.iluwatar.doubledispatch.constants.AppConstants;
/** /**
* * Meteoroid game object.
* Meteoroid game object
*
*/ */
public class Meteoroid extends GameObject { public class Meteoroid extends GameObject {
@ -48,12 +45,14 @@ public class Meteoroid extends GameObject {
@Override @Override
public void collisionResolve(FlamingAsteroid asteroid) { public void collisionResolve(FlamingAsteroid asteroid) {
LOGGER.info(AppConstants.HITS, asteroid.getClass().getSimpleName(), this.getClass().getSimpleName()); LOGGER.info(AppConstants.HITS, asteroid.getClass().getSimpleName(), this.getClass()
.getSimpleName());
} }
@Override @Override
public void collisionResolve(Meteoroid meteoroid) { public void collisionResolve(Meteoroid meteoroid) {
LOGGER.info(AppConstants.HITS, meteoroid.getClass().getSimpleName(), this.getClass().getSimpleName()); LOGGER.info(AppConstants.HITS, meteoroid.getClass().getSimpleName(), this.getClass()
.getSimpleName());
} }
@Override @Override

View File

@ -24,9 +24,7 @@
package com.iluwatar.doubledispatch; package com.iluwatar.doubledispatch;
/** /**
*
* Rectangle has coordinates and can be checked for overlap against other Rectangles. * Rectangle has coordinates and can be checked for overlap against other Rectangles.
*
*/ */
public class Rectangle { public class Rectangle {
@ -36,7 +34,7 @@ public class Rectangle {
private int bottom; private int bottom;
/** /**
* Constructor * Constructor.
*/ */
public Rectangle(int left, int top, int right, int bottom) { public Rectangle(int left, int top, int right, int bottom) {
this.left = left; this.left = left;

View File

@ -24,9 +24,7 @@
package com.iluwatar.doubledispatch; package com.iluwatar.doubledispatch;
/** /**
* * Space station ISS game object.
* Space station ISS game object
*
*/ */
public class SpaceStationIss extends SpaceStationMir { public class SpaceStationIss extends SpaceStationMir {

View File

@ -23,15 +23,12 @@
package com.iluwatar.doubledispatch; package com.iluwatar.doubledispatch;
import com.iluwatar.doubledispatch.constants.AppConstants;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.iluwatar.doubledispatch.constants.AppConstants;
/** /**
* * Space station Mir game object.
* Space station Mir game object
*
*/ */
public class SpaceStationMir extends GameObject { public class SpaceStationMir extends GameObject {
@ -48,29 +45,31 @@ public class SpaceStationMir extends GameObject {
@Override @Override
public void collisionResolve(FlamingAsteroid asteroid) { public void collisionResolve(FlamingAsteroid asteroid) {
LOGGER.info(AppConstants.HITS," {} is damaged! {} is set on fire!", asteroid.getClass().getSimpleName(), LOGGER.info(AppConstants.HITS, " {} is damaged! {} is set on fire!", asteroid.getClass()
this.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass().getSimpleName()); .getSimpleName(),
this.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass()
.getSimpleName());
setDamaged(true); setDamaged(true);
setOnFire(true); setOnFire(true);
} }
@Override @Override
public void collisionResolve(Meteoroid meteoroid) { public void collisionResolve(Meteoroid meteoroid) {
LOGGER.info(AppConstants.HITS," {} is damaged!", meteoroid.getClass().getSimpleName(), LOGGER.info(AppConstants.HITS, " {} is damaged!", meteoroid.getClass().getSimpleName(),
this.getClass().getSimpleName(), this.getClass().getSimpleName()); this.getClass().getSimpleName(), this.getClass().getSimpleName());
setDamaged(true); setDamaged(true);
} }
@Override @Override
public void collisionResolve(SpaceStationMir mir) { public void collisionResolve(SpaceStationMir mir) {
LOGGER.info(AppConstants.HITS," {} is damaged!", mir.getClass().getSimpleName(), LOGGER.info(AppConstants.HITS, " {} is damaged!", mir.getClass().getSimpleName(),
this.getClass().getSimpleName(), this.getClass().getSimpleName()); this.getClass().getSimpleName(), this.getClass().getSimpleName());
setDamaged(true); setDamaged(true);
} }
@Override @Override
public void collisionResolve(SpaceStationIss iss) { public void collisionResolve(SpaceStationIss iss) {
LOGGER.info(AppConstants.HITS," {} is damaged!", iss.getClass().getSimpleName(), LOGGER.info(AppConstants.HITS, " {} is damaged!", iss.getClass().getSimpleName(),
this.getClass().getSimpleName(), this.getClass().getSimpleName()); this.getClass().getSimpleName(), this.getClass().getSimpleName());
setDamaged(true); setDamaged(true);
} }

View File

@ -24,9 +24,7 @@
package com.iluwatar.doubledispatch.constants; package com.iluwatar.doubledispatch.constants;
/** /**
* * Constants class to define all constants.
* Constants class to define all constants
*
*/ */
public class AppConstants { public class AppConstants {