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:
parent
01e489c77b
commit
f2c91eb836
@ -28,23 +28,25 @@ import com.iluwatar.delegation.simple.printers.EpsonPrinter;
|
||||
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 class being called in this case {@link PrinterController} is not responsible for the actual desired action,
|
||||
* but is actually delegated to a helper class either {@link CanonPrinter}, {@link EpsonPrinter} or {@link HpPrinter}.
|
||||
* The consumer does not have or require knowledge of the actual class carrying out the action, only the
|
||||
* container on which they are calling.
|
||||
* The delegate pattern provides a mechanism to abstract away the implementation and control of the
|
||||
* desired action. The class being called in this case {@link PrinterController} is not responsible
|
||||
* for the actual desired action, but is actually delegated to a helper class either {@link
|
||||
* CanonPrinter}, {@link EpsonPrinter} or {@link HpPrinter}. The consumer does not have or require
|
||||
* 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
|
||||
* {@link Printer}. The {@link PrinterController} class also implements {@link Printer}. However neither provide the
|
||||
* functionality of {@link Printer} by 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.
|
||||
* <p>In this example the delegates are {@link EpsonPrinter}, {@link HpPrinter} and {@link
|
||||
* CanonPrinter} they all implement {@link Printer}. The {@link PrinterController} class also
|
||||
* implements {@link Printer}. However neither provide the functionality of {@link Printer} by
|
||||
* 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 {
|
||||
|
||||
private static final String MESSAGE_TO_PRINT = "hello world";
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
|
@ -38,7 +38,8 @@ public interface Printer {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -24,10 +24,10 @@
|
||||
package com.iluwatar.delegation.simple;
|
||||
|
||||
/**
|
||||
* Delegator Class to delegate the implementation of the Printer.
|
||||
* This ensures two things:
|
||||
* - 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 delegation control
|
||||
* Delegator Class to delegate the implementation of the Printer. This ensures two things: - 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
|
||||
* delegation control
|
||||
*/
|
||||
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
|
||||
* implementation, it instead calls upon the class passed through the constructor. This is the delegate,
|
||||
* hence the pattern. Therefore meaning that the caller does not care of the implementing class only the owning
|
||||
* controller.
|
||||
* This method is implemented from {@link Printer} however instead on providing an implementation,
|
||||
* it instead calls upon the class passed through the constructor. This is the delegate, hence the
|
||||
* pattern. Therefore meaning that the caller does not care of the implementing class only the
|
||||
* owning controller.
|
||||
*
|
||||
* @param message to be printed to the screen
|
||||
*/
|
||||
|
@ -28,8 +28,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Specialised Implementation of {@link Printer} for a Canon Printer, in
|
||||
* this case the message to be printed is appended to "Canon Printer : "
|
||||
* Specialised Implementation of {@link Printer} for a Canon Printer, in this case the message to be
|
||||
* printed is appended to "Canon Printer : ".
|
||||
*
|
||||
* @see Printer
|
||||
*/
|
||||
|
@ -28,8 +28,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Specialised Implementation of {@link Printer} for a Epson Printer, in
|
||||
* this case the message to be printed is appended to "Epson Printer : "
|
||||
* Specialised Implementation of {@link Printer} for a Epson Printer, in this case the message to be
|
||||
* printed is appended to "Epson Printer : ".
|
||||
*
|
||||
* @see Printer
|
||||
*/
|
||||
|
@ -28,8 +28,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Specialised Implementation of {@link Printer} for a HP Printer, in
|
||||
* this case the message to be printed is appended to "HP Printer : "
|
||||
* Specialised Implementation of {@link Printer} for a HP Printer, in this case the message to be
|
||||
* printed is appended to "HP Printer : ".
|
||||
*
|
||||
* @see Printer
|
||||
*/
|
||||
|
@ -23,30 +23,6 @@
|
||||
|
||||
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
|
||||
* through its setter.
|
||||
|
@ -24,10 +24,8 @@
|
||||
package com.iluwatar.dependency.injection;
|
||||
|
||||
/**
|
||||
*
|
||||
* AdvancedWizard implements inversion of control. It depends on abstraction that can be injected
|
||||
* through its constructor.
|
||||
*
|
||||
*/
|
||||
public class AdvancedWizard implements Wizard {
|
||||
|
||||
|
@ -31,25 +31,26 @@ import com.google.inject.Injector;
|
||||
* 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.
|
||||
* - 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
|
||||
* naive implementation violating the inversion of control principle. It depends directly on a
|
||||
*
|
||||
* <p>In this example we show you three different wizards. The first one ({@link SimpleWizard}) is
|
||||
* a naive implementation violating the inversion of control principle. It depends directly on a
|
||||
* concrete implementation which cannot be changed.
|
||||
* <p>
|
||||
* The second and third wizards({@link AdvancedWizard} and {@link AdvancedSorceress}) are more flexible.
|
||||
* They do not depend on any concrete implementation but abstraction. They utilizes Dependency Injection
|
||||
* pattern allowing their {@link Tobacco} dependency to be injected through constructor ({@link AdvancedWizard})
|
||||
* or setter ({@link AdvancedSorceress}). This way, handling the dependency is no longer the wizard's
|
||||
* responsibility. It is resolved outside the wizard class.
|
||||
* <p>
|
||||
* The fourth example takes the pattern a step further. It uses Guice framework for Dependency
|
||||
*
|
||||
* <p>The second and third wizards({@link AdvancedWizard} and {@link AdvancedSorceress}) are more
|
||||
* flexible. They do not depend on any concrete implementation but abstraction. They utilizes
|
||||
* Dependency Injection pattern allowing their {@link Tobacco} dependency to be injected through
|
||||
* constructor ({@link AdvancedWizard}) or setter ({@link AdvancedSorceress}). This way, handling
|
||||
* the dependency is no longer the wizard's responsibility. It is resolved outside the wizard
|
||||
* class.
|
||||
*
|
||||
* <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
|
||||
* used to create {@link GuiceWizard} object with correct dependencies.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
|
@ -26,10 +26,8 @@ package com.iluwatar.dependency.injection;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* GuiceWizard implements inversion of control. Its dependencies are injected through its
|
||||
* constructor by Guice framework.
|
||||
*
|
||||
*/
|
||||
public class GuiceWizard implements Wizard {
|
||||
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.dependency.injection;
|
||||
|
||||
/**
|
||||
*
|
||||
* OldTobyTobacco concrete {@link Tobacco} implementation
|
||||
*
|
||||
* OldTobyTobacco concrete {@link Tobacco} implementation.
|
||||
*/
|
||||
public class OldTobyTobacco extends Tobacco {
|
||||
}
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.dependency.injection;
|
||||
|
||||
/**
|
||||
*
|
||||
* RivendellTobacco concrete {@link Tobacco} implementation
|
||||
*
|
||||
* RivendellTobacco concrete {@link Tobacco} implementation.
|
||||
*/
|
||||
public class RivendellTobacco extends Tobacco {
|
||||
}
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.dependency.injection;
|
||||
|
||||
/**
|
||||
*
|
||||
* SecondBreakfastTobacco concrete {@link Tobacco} implementation
|
||||
*
|
||||
* SecondBreakfastTobacco concrete {@link Tobacco} implementation.
|
||||
*/
|
||||
public class SecondBreakfastTobacco extends Tobacco {
|
||||
}
|
||||
|
@ -24,10 +24,8 @@
|
||||
package com.iluwatar.dependency.injection;
|
||||
|
||||
/**
|
||||
*
|
||||
* Naive Wizard implementation violating the inversion of control principle. It should depend on
|
||||
* abstraction instead.
|
||||
*
|
||||
*/
|
||||
public class SimpleWizard implements Wizard {
|
||||
|
||||
|
@ -27,9 +27,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* Tobacco abstraction
|
||||
*
|
||||
* Tobacco abstraction.
|
||||
*/
|
||||
public abstract class Tobacco {
|
||||
|
||||
|
@ -26,9 +26,7 @@ package com.iluwatar.dependency.injection;
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
/**
|
||||
*
|
||||
* Guice module for binding certain concrete {@link Tobacco} implementation.
|
||||
*
|
||||
*/
|
||||
public class TobaccoModule extends AbstractModule {
|
||||
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.dependency.injection;
|
||||
|
||||
/**
|
||||
*
|
||||
* Wizard interface
|
||||
*
|
||||
* Wizard interface.
|
||||
*/
|
||||
public interface Wizard {
|
||||
|
||||
|
@ -23,45 +23,49 @@
|
||||
|
||||
package com.iluwatar.dirtyflag;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
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 they’re 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
|
||||
* 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 they’re requested. Once the
|
||||
* results are re-calculated, then the bool value can be cleared.
|
||||
*
|
||||
* There are some points that need to be considered before diving into using this pattern:- there are some things you’ll
|
||||
* need to consider:- (1) Do you need it? This design pattern works well when the results to be calculated are difficult
|
||||
* or resource intensive to compute. You want to save them. You also don’t want to be calculating them several times in
|
||||
* 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
|
||||
* 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.
|
||||
* <p>There are some points that need to be considered before diving into using this pattern:-
|
||||
* there are some things you’ll need to consider:- (1) Do you need it? This design pattern works
|
||||
* well when the results to be calculated are difficult or resource intensive to compute. You want
|
||||
* to save them. You also don’t want to be calculating them several times in 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
|
||||
* 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>
|
||||
* when needed. {@link World} mainly serves the data to the front-end.
|
||||
* <p>In this example, the {@link DataFetcher} holds the <i>dirty flag</i>. It fetches and
|
||||
* re-fetches from <i>world.txt</i> when needed. {@link World} mainly serves the data to the
|
||||
* front-end.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
|
||||
/**
|
||||
* Program execution point
|
||||
* Program execution point.
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
executorService.scheduleAtFixedRate(new Runnable() {
|
||||
final World world = new World();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<String> countries = world.fetch();
|
||||
@ -74,10 +78,9 @@ public class App {
|
||||
}
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args
|
||||
* command line args
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
App app = new App();
|
||||
|
@ -23,22 +23,19 @@
|
||||
|
||||
package com.iluwatar.dirtyflag;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.xml.crypto.Data;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A mock database manager -- Fetches data from a raw file.
|
||||
*
|
||||
* @author swaisuan
|
||||
*
|
||||
* @author swaisuan
|
||||
*/
|
||||
public class DataFetcher {
|
||||
|
||||
@ -61,7 +58,7 @@ public class DataFetcher {
|
||||
|
||||
/**
|
||||
* Fetches data/content from raw file.
|
||||
*
|
||||
*
|
||||
* @return List of strings
|
||||
*/
|
||||
public List<String> fetch() {
|
||||
|
@ -27,11 +27,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* A middle-layer app that calls/passes along data from the back-end.
|
||||
*
|
||||
* @author swaisuan
|
||||
*
|
||||
* @author swaisuan
|
||||
*/
|
||||
public class World {
|
||||
|
||||
@ -44,9 +42,8 @@ public class World {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Calls {@link DataFetcher} to fetch data from back-end.
|
||||
*
|
||||
*
|
||||
* @return List of strings
|
||||
*/
|
||||
public List<String> fetch() {
|
||||
|
@ -23,21 +23,19 @@
|
||||
|
||||
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.Pair;
|
||||
import org.slf4j.Logger;
|
||||
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.
|
||||
* The usage of multiple buffers increases the overall throughput of a device
|
||||
* and helps prevents bottlenecks. This example shows using double buffer pattern
|
||||
* on graphics. It is used to show one image or frame while a separate frame
|
||||
* is being buffered to be shown next. This method makes animations and games
|
||||
* look more realistic than the same done in a single buffer mode.
|
||||
* Double buffering is a term used to describe a device that has two buffers. The usage of multiple
|
||||
* buffers increases the overall throughput of a device and helps prevents bottlenecks. This example
|
||||
* shows using double buffer pattern on graphics. It is used to show one image or frame while a
|
||||
* separate frame is being buffered to be shown next. This method makes animations and games look
|
||||
* more realistic than the same done in a single buffer mode.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
@ -45,10 +43,11 @@ public class App {
|
||||
|
||||
/**
|
||||
* Program main entry point.
|
||||
*
|
||||
* @param args runtime arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
var scene = new Scene();
|
||||
final var scene = new Scene();
|
||||
List<Pair<Integer, Integer>> drawPixels = new ArrayList<>();
|
||||
Pair<Integer, Integer> pixel1 = new MutablePair<>(1, 1);
|
||||
Pair<Integer, Integer> pixel2 = new MutablePair<>(5, 6);
|
||||
|
@ -30,6 +30,7 @@ public interface Buffer {
|
||||
|
||||
/**
|
||||
* Clear the pixel in (x, y).
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
*/
|
||||
@ -37,6 +38,7 @@ public interface Buffer {
|
||||
|
||||
/**
|
||||
* Draw the pixel in (x, y).
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
*/
|
||||
@ -49,6 +51,7 @@ public interface Buffer {
|
||||
|
||||
/**
|
||||
* Get all the pixels.
|
||||
*
|
||||
* @return pixel list
|
||||
*/
|
||||
Pixel[] getPixels();
|
||||
|
@ -23,9 +23,6 @@
|
||||
|
||||
package com.iluwatar.doublebuffer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* FrameBuffer implementation class.
|
||||
*/
|
||||
|
@ -23,12 +23,11 @@
|
||||
|
||||
package com.iluwatar.doublebuffer;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Scene class. Render the output frame.
|
||||
*/
|
||||
@ -55,6 +54,7 @@ public class Scene {
|
||||
|
||||
/**
|
||||
* Draw the next frame.
|
||||
*
|
||||
* @param coordinateList list of pixels of which the color should be black
|
||||
*/
|
||||
public void draw(List<Pair<Integer, Integer>> coordinateList) {
|
||||
|
@ -23,32 +23,30 @@
|
||||
|
||||
package com.iluwatar.doublechecked.locking;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
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
|
||||
* 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
|
||||
* locking logic proceed.
|
||||
* <p>
|
||||
* In {@link Inventory} we store the items with a given size. However, we do not store more items
|
||||
* than the inventory size. To address concurrent access problems we use double checked locking to
|
||||
* add item to inventory. In this method, the thread which gets the lock first adds the item.
|
||||
*
|
||||
*
|
||||
* <p>In {@link Inventory} we store the items with a given size. However, we do not store more
|
||||
* items than the inventory size. To address concurrent access problems we use double checked
|
||||
* locking to add item to inventory. In this method, the thread which gets the lock first adds the
|
||||
* item.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
@ -23,19 +23,16 @@
|
||||
|
||||
package com.iluwatar.doublechecked.locking;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* Inventory
|
||||
*
|
||||
* Inventory.
|
||||
*/
|
||||
public class Inventory {
|
||||
|
||||
@ -46,7 +43,7 @@ public class Inventory {
|
||||
private final Lock lock;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Constructor.
|
||||
*/
|
||||
public Inventory(int inventorySize) {
|
||||
this.inventorySize = inventorySize;
|
||||
@ -55,7 +52,7 @@ public class Inventory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add item
|
||||
* Add item.
|
||||
*/
|
||||
public boolean addItem(Item item) {
|
||||
if (items.size() < inventorySize) {
|
||||
@ -63,7 +60,8 @@ public class Inventory {
|
||||
try {
|
||||
if (items.size() < inventorySize) {
|
||||
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;
|
||||
}
|
||||
} 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
|
||||
*/
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.doublechecked.locking;
|
||||
|
||||
/**
|
||||
*
|
||||
* Item
|
||||
*
|
||||
* Item.
|
||||
*/
|
||||
public class Item {
|
||||
}
|
||||
|
@ -23,46 +23,45 @@
|
||||
|
||||
package com.iluwatar.doubledispatch;
|
||||
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
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 implementation of
|
||||
* that method in the receiver. Sometimes the behaviour must also be determined by 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.
|
||||
* When a message with a parameter is sent to an object, the resultant behaviour is defined by the
|
||||
* implementation of that method in the receiver. Sometimes the behaviour must also be determined by
|
||||
* 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.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args
|
||||
* command line args
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// initialize game objects and print their status
|
||||
List<GameObject> objects = List.of(
|
||||
new FlamingAsteroid(0, 0, 5, 5),
|
||||
new SpaceStationMir(1, 1, 2, 2),
|
||||
new Meteoroid(10, 10, 15, 15),
|
||||
new SpaceStationIss(12, 12, 14, 14));
|
||||
new FlamingAsteroid(0, 0, 5, 5),
|
||||
new SpaceStationMir(1, 1, 2, 2),
|
||||
new Meteoroid(10, 10, 15, 15),
|
||||
new SpaceStationIss(12, 12, 14, 14));
|
||||
objects.stream().forEach(o -> LOGGER.info(o.toString()));
|
||||
LOGGER.info("");
|
||||
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.doubledispatch;
|
||||
|
||||
/**
|
||||
*
|
||||
* Flaming asteroid game object
|
||||
*
|
||||
* Flaming asteroid game object.
|
||||
*/
|
||||
public class FlamingAsteroid extends Meteoroid {
|
||||
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.doubledispatch;
|
||||
|
||||
/**
|
||||
*
|
||||
* Game objects have coordinates and some other status information.
|
||||
*
|
||||
*/
|
||||
public abstract class GameObject extends Rectangle {
|
||||
|
||||
|
@ -23,15 +23,12 @@
|
||||
|
||||
package com.iluwatar.doubledispatch;
|
||||
|
||||
import com.iluwatar.doubledispatch.constants.AppConstants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.iluwatar.doubledispatch.constants.AppConstants;
|
||||
|
||||
/**
|
||||
*
|
||||
* Meteoroid game object
|
||||
*
|
||||
* Meteoroid game object.
|
||||
*/
|
||||
public class Meteoroid extends GameObject {
|
||||
|
||||
@ -48,12 +45,14 @@ public class Meteoroid extends GameObject {
|
||||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.doubledispatch;
|
||||
|
||||
/**
|
||||
*
|
||||
* Rectangle has coordinates and can be checked for overlap against other Rectangles.
|
||||
*
|
||||
*/
|
||||
public class Rectangle {
|
||||
|
||||
@ -36,7 +34,7 @@ public class Rectangle {
|
||||
private int bottom;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Constructor.
|
||||
*/
|
||||
public Rectangle(int left, int top, int right, int bottom) {
|
||||
this.left = left;
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.doubledispatch;
|
||||
|
||||
/**
|
||||
*
|
||||
* Space station ISS game object
|
||||
*
|
||||
* Space station ISS game object.
|
||||
*/
|
||||
public class SpaceStationIss extends SpaceStationMir {
|
||||
|
||||
|
@ -23,15 +23,12 @@
|
||||
|
||||
package com.iluwatar.doubledispatch;
|
||||
|
||||
import com.iluwatar.doubledispatch.constants.AppConstants;
|
||||
import org.slf4j.Logger;
|
||||
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 {
|
||||
|
||||
@ -48,29 +45,31 @@ public class SpaceStationMir extends GameObject {
|
||||
|
||||
@Override
|
||||
public void collisionResolve(FlamingAsteroid asteroid) {
|
||||
LOGGER.info(AppConstants.HITS," {} is damaged! {} is set on fire!", asteroid.getClass().getSimpleName(),
|
||||
this.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass().getSimpleName());
|
||||
LOGGER.info(AppConstants.HITS, " {} is damaged! {} is set on fire!", asteroid.getClass()
|
||||
.getSimpleName(),
|
||||
this.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass()
|
||||
.getSimpleName());
|
||||
setDamaged(true);
|
||||
setOnFire(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
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());
|
||||
setDamaged(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
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());
|
||||
setDamaged(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
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());
|
||||
setDamaged(true);
|
||||
}
|
||||
|
@ -24,9 +24,7 @@
|
||||
package com.iluwatar.doubledispatch.constants;
|
||||
|
||||
/**
|
||||
*
|
||||
* Constants class to define all constants
|
||||
*
|
||||
* Constants class to define all constants.
|
||||
*/
|
||||
public class AppConstants {
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user