Compare commits

..

39 Commits
1.7.0 ... 1.8.0

Author SHA1 Message Date
f018d13c39 Set version number for monthly release 2015-12-02 23:21:44 +02:00
5bec63659f Merge pull request #305 from hoswey/master
Fix #216 Repository vs DAO
2015-11-28 00:09:27 +02:00
9d4fff6029 Fix #216 Repository vs DAO 2015-11-27 11:22:33 +08:00
092d48d150 Merge pull request #294 from DevFactory/release1
Unit tests for adapter, business-delegate, factory-method and command modules
2015-11-22 08:44:13 +02:00
6b99f2669e Added capability for test coverage report generation and steps to do so. 2015-11-22 05:47:36 +05:30
ced317bc9d Added UnitTest cases for factory method. 2015-11-22 05:46:14 +05:30
e5614e5a20 Added UnitTest cases for command. 2015-11-22 05:45:45 +05:30
012b638023 Added UnitTest cases for business delegate. 2015-11-22 05:45:14 +05:30
b577890db4 Added UnitTest cases for adapter. 2015-11-22 05:44:45 +05:30
8ba0192864 Add EIP tag to relevant patterns 2015-11-21 16:34:59 +02:00
899b9617c9 Merge pull request #295 from iluwatar/JaXt0r-publish-subscribe
Jaxt0r publish subscribe
2015-11-21 16:10:34 +02:00
d0fca6d318 Improve the example and documentation 2015-11-21 16:05:55 +02:00
7885380633 Apply Google coding conventions 2015-11-21 15:12:31 +02:00
230c02fb24 Fix spelling 2015-11-21 15:09:23 +02:00
b97e9207a7 Update version number for Publish-Subscribe 2015-11-21 15:03:27 +02:00
8519e13de6 Merge branch 'publish-subscribe' of https://github.com/JaXt0r/java-design-patterns into JaXt0r-publish-subscribe
Conflicts:
	pom.xml
2015-11-21 14:55:02 +02:00
ba3f583467 Merge pull request #290 from hoswey/master
implements Twin design pattern #63
2015-11-16 21:09:41 +02:00
142274f3f7 implements Twin design pattern #63, add credit and rephrase the comments 2015-11-16 10:01:03 +08:00
5b06c52fff Merge pull request #291 from tainarareis/abstract-factory
Issue #286: Added main method in Abstract Factory Example
2015-11-14 21:33:48 +02:00
033f8e740d Merge pull request #287 from l-cortese/master
log4j.xml relocated and excluded from JAR
2015-11-14 21:19:50 +02:00
34528173b7 Issue #286: Added main method in Abstract Factory Example 2015-11-14 16:48:19 -02:00
fdbfa9e8ee implements Twin design pattern #63 2015-11-14 17:38:35 +08:00
bf65168776 corrected typos in the comments 2015-11-13 22:35:30 +01:00
043a610754 log4j.xml relocated due to visibility issues and excluded from generated
JAR. pom.xml formatted according to coding conventions
2015-11-13 18:34:10 +01:00
27199325ec Merge pull request #284 from hoswey/master
correct the package name for producer-consumer test folder
2015-11-07 11:48:51 +02:00
960b568fbb correct the package name for producer-consumer test folder 2015-11-07 15:51:16 +08:00
c02e65fa3a Added alias names for GOF patterns #267 2015-11-04 21:13:32 +02:00
fe63c9cec4 Merge pull request #281 from ankurkaushal/master
Reformat according to google style guide
2015-11-02 21:39:17 +02:00
7e4f04602e Merge pull request #282 from l-cortese/master
Corrected Freddy's last name
2015-11-02 21:36:20 +02:00
306b1f3d31 Reformat rest of the design patterns - Issue #224 2015-11-01 21:29:13 -05:00
449340bd2b Reformat business-delegate, callback, chain, command, composite, dao, decorator & dependency-injection patterns. 2015-11-01 18:48:43 -05:00
3af06a3a3a Reformat builder pattern - issue #224 2015-11-01 18:03:29 -05:00
e7b6542134 Reformat bridge design pattern - Issue #224 2015-11-01 17:43:54 -05:00
16a8c85af6 Reformat Async Method Invocation - Issue #224 2015-11-01 17:33:25 -05:00
95c16200e7 Reformat Adapter Pattern - Issue #224 2015-11-01 17:26:57 -05:00
c0c21ebd91 Reformat Abstract Factory - Issue #224 2015-11-01 17:18:39 -05:00
25c1f87d46 Corrected Freddy's second name 2015-11-01 23:15:57 +01:00
c6ca80b25f Bump version number for the next development iteration 2015-11-01 22:22:31 +02:00
ac5c1967df #161 - Publish Subscribe Channel realisation.Heavily based on iluwatars Message Channel implementation (#143). 2015-10-25 07:11:34 +01:00
550 changed files with 9808 additions and 8604 deletions

13
CODE_COVERAGE.md Normal file
View File

@ -0,0 +1,13 @@
# Code Coverage Report generation
To generate the code coverage report, execute the following command:
> mvn clean verify
This will generate code coverage report in each of the modules. In order to view the same, open the following file in your browser.
> target/site/jacoco/index.html
Please note that the above folder is created under each of the modules. For example:
* adapter/target/site/jacoco/index.html
* busniess-delegate/target/site/jacoco/index.html

View File

@ -9,6 +9,8 @@ tags:
- Gang Of Four - Gang Of Four
--- ---
**Also known as:** Kit
**Intent:** Provide an interface for creating families of related or dependent **Intent:** Provide an interface for creating families of related or dependent
objects without specifying their concrete classes. objects without specifying their concrete classes.

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>abstract-factory</artifactId> <artifactId>abstract-factory</artifactId>
<dependencies> <dependencies>

View File

@ -3,21 +3,18 @@ package com.iluwatar.abstractfactory;
/** /**
* *
* The Abstract Factory pattern provides a way to encapsulate a group of individual * The Abstract Factory pattern provides a way to encapsulate a group of individual factories that
* factories that have a common theme without specifying their concrete classes. In * have a common theme without specifying their concrete classes. In normal usage, the client
* normal usage, the client software creates a concrete implementation of the abstract * software creates a concrete implementation of the abstract factory and then uses the generic
* factory and then uses the generic interface of the factory to create the concrete * interface of the factory to create the concrete objects that are part of the theme. The client
* objects that are part of the theme. The client does not know (or care) which * does not know (or care) which concrete objects it gets from each of these internal factories,
* concrete objects it gets from each of these internal factories, since it uses only * since it uses only the generic interfaces of their products. This pattern separates the details
* the generic interfaces of their products. This pattern separates the details of * of implementation of a set of objects from their general usage and relies on object composition,
* implementation of a set of objects from their general usage and relies on object * as object creation is implemented in methods exposed in the factory interface.
* composition, as object creation is implemented in methods exposed in the factory
* interface.
* <p> * <p>
* The essence of the Abstract Factory pattern is a factory interface * The essence of the Abstract Factory pattern is a factory interface ({@link KingdomFactory}) and
* ({@link KingdomFactory}) and its implementations ({@link ElfKingdomFactory}, * its implementations ({@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses both
* {@link OrcKingdomFactory}). The example uses both concrete implementations to * concrete implementations to create a king, a castle and an army.
* create a king, a castle and an army.
* *
*/ */
public class App { public class App {
@ -26,8 +23,10 @@ public class App {
private Castle castle; private Castle castle;
private Army army; private Army army;
/** /**
* Creates kingdom * Creates kingdom
*
* @param factory * @param factory
*/ */
public void createKingdom(final KingdomFactory factory) { public void createKingdom(final KingdomFactory factory) {
@ -79,4 +78,33 @@ public class App {
private void setArmy(final Army army) { private void setArmy(final Army army) {
this.army = army; this.army = army;
} }
/**
* Program entry point
*
* @param args command line args
*/
public static void main(String[] args) {
App app = new App();
System.out.println("Elf Kingdom");
KingdomFactory elfKingdomFactory;
elfKingdomFactory = app.getElfKingdomFactory();
app.createKingdom(elfKingdomFactory);
System.out.println(app.getArmy().getDescription());
System.out.println(app.getCastle().getDescription());
System.out.println(app.getKing().getDescription());
System.out.println("\nOrc Kingdom");
KingdomFactory orcKingdomFactory;
orcKingdomFactory = app.getOrcKingdomFactory();
app.createKingdom(orcKingdomFactory);
System.out.println(app.getArmy().getDescription());
System.out.println(app.getCastle().getDescription());
System.out.println(app.getKing().getDescription());
}
} }

View File

@ -7,7 +7,7 @@ package com.iluwatar.abstractfactory;
*/ */
public class OrcKing implements King { public class OrcKing implements King {
static final String DESCRIPTION = "This is the Orc king!"; static final String DESCRIPTION = "This is the Orc king!";
@Override @Override
public String getDescription() { public String getDescription() {

View File

@ -18,5 +18,4 @@ public class OrcKingdomFactory implements KingdomFactory {
public Army createArmy() { public Army createArmy() {
return new OrcArmy(); return new OrcArmy();
} }
} }

View File

@ -1,4 +1,5 @@
package com.iluwatar.abstractfactory; package com.iluwatar.abstractfactory;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;

View File

@ -9,6 +9,8 @@ tags:
- Gang Of Four - Gang Of Four
--- ---
**Also known as:** Wrapper
**Intent:** Convert the interface of a class into another interface the clients **Intent:** Convert the interface of a class into another interface the clients
expect. Adapter lets classes work together that couldn't otherwise because of expect. Adapter lets classes work together that couldn't otherwise because of
incompatible interfaces. incompatible interfaces.

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>adapter</artifactId> <artifactId>adapter</artifactId>
<dependencies> <dependencies>
@ -14,5 +14,10 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,31 +1,28 @@
package com.iluwatar.adapter; package com.iluwatar.adapter;
/** /**
* An adapter helps two incompatible interfaces to work together. This is the real world definition
* for an adapter. Interfaces may be incompatible but the inner functionality should suit the need.
* The Adapter design pattern allows otherwise incompatible classes to work together by converting
* the interface of one class into an interface expected by the clients.
* *
* An adapter helps two incompatible interfaces to work together. This is the real * <p>There are two variations of the Adapter pattern: The class adapter implements the adaptee's
* world definition for an adapter. Interfaces may be incompatible but the inner * interface whereas the object adapter uses composition to contain the adaptee in the adapter
* functionality should suit the need. The Adapter design pattern allows otherwise * object. This example uses the object adapter approach.
* incompatible classes to work together by converting the interface of one class
* into an interface expected by the clients.
* <p>
* There are two variations of the Adapter pattern: The class adapter implements
* the adaptee's interface whereas the object adapter uses composition to
* contain the adaptee in the adapter object. This example uses the object
* adapter approach.
* <p>
* The Adapter ({@link GnomeEngineer}) converts the interface of the target class
* ({@link GoblinGlider}) into a suitable one expected by the client
* ({@link GnomeEngineeringManager}).
* *
* <p>The Adapter ({@link GnomeEngineer}) converts the interface of the target class (
* {@link GoblinGlider}) into a suitable one expected by the client ({@link GnomeEngineeringManager}
* ).
*/ */
public class App { 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) { public static void main(String[] args) {
Engineer manager = new GnomeEngineeringManager(); Engineer manager = new GnomeEngineeringManager(new GnomeEngineer());
manager.operateDevice(); manager.operateDevice();
} }
} }

View File

@ -8,5 +8,4 @@ package com.iluwatar.adapter;
public interface Engineer { public interface Engineer {
void operateDevice(); void operateDevice();
} }

View File

@ -2,8 +2,8 @@ package com.iluwatar.adapter;
/** /**
* *
* Adapter class. Adapts the interface of the device ({@link GoblinGlider}) into * Adapter class. Adapts the interface of the device ({@link GoblinGlider}) into {@link Engineer}
* {@link Engineer} interface expected by the client ({@link GnomeEngineeringManager}). * interface expected by the client ({@link GnomeEngineeringManager}).
* *
*/ */
public class GnomeEngineer implements Engineer { public class GnomeEngineer implements Engineer {
@ -20,5 +20,4 @@ public class GnomeEngineer implements Engineer {
glider.gainSpeed(); glider.gainSpeed();
glider.takeOff(); glider.takeOff();
} }
} }

View File

@ -1,20 +1,26 @@
package com.iluwatar.adapter; package com.iluwatar.adapter;
/** /**
*
* GnomeEngineering manager uses {@link Engineer} to operate devices. * GnomeEngineering manager uses {@link Engineer} to operate devices.
*
*/ */
public class GnomeEngineeringManager implements Engineer { public class GnomeEngineeringManager implements Engineer {
private Engineer engineer; private Engineer engineer;
public GnomeEngineeringManager() { public GnomeEngineeringManager() {
engineer = new GnomeEngineer();
}
public GnomeEngineeringManager(Engineer engineer) {
this.engineer = engineer;
} }
@Override @Override
public void operateDevice() { public void operateDevice() {
engineer.operateDevice(); engineer.operateDevice();
} }
public void setEngineer(Engineer engineer) {
this.engineer = engineer;
}
} }

View File

@ -0,0 +1,68 @@
package com.iluwatar.adapter;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
/**
* An adapter helps two incompatible interfaces to work together. This is the real world definition
* for an adapter. Interfaces may be incompatible but the inner functionality should suit the need.
* The Adapter design pattern allows otherwise incompatible classes to work together by converting
* the interface of one class into an interface expected by the clients.
*
* <p>There are two variations of the Adapter pattern:
* The class adapter implements the adaptee's
* interface whereas the object adapter uses composition to contain the adaptee in the adapter
* object. This example uses the object adapter approach.
*
* <p>The Adapter ({@link GnomeEngineer}) converts the interface
* of the target class ({@link GoblinGlider}) into a suitable one expected by
* the client ({@link GnomeEngineeringManager}
* ).
*/
public class AdapterPatternTest {
private Map<String, Object> beans;
private static final String ENGINEER_BEAN = "engineer";
private static final String MANAGER_BEAN = "manager";
/**
* This method runs before the test execution and sets the bean objects in the beans Map.
*/
@Before
public void setup() {
beans = new HashMap<>();
GnomeEngineer gnomeEngineer = spy(new GnomeEngineer());
beans.put(ENGINEER_BEAN, gnomeEngineer);
GnomeEngineeringManager manager = new GnomeEngineeringManager();
manager.setEngineer((GnomeEngineer) beans.get(ENGINEER_BEAN));
beans.put(MANAGER_BEAN, manager);
}
/**
* This test asserts that when we call operateDevice() method on a manager bean, it is internally
* calling operateDevice method on the engineer object. The Adapter ({@link GnomeEngineer})
* converts the interface of the target class ( {@link GoblinGlider}) into a suitable one expected
* by the client ({@link GnomeEngineeringManager} ).
*/
@Test
public void testAdapter() {
Engineer manager = (Engineer) beans.get(MANAGER_BEAN);
// when manager is asked to operate device
manager.operateDevice();
// Manager internally calls the engineer object to operateDevice
Engineer engineer = (Engineer) beans.get(ENGINEER_BEAN);
verify(engineer).operateDevice();
}
}

View File

@ -1,19 +0,0 @@
package com.iluwatar.adapter;
import org.junit.Test;
import com.iluwatar.adapter.App;
/**
*
* Application test
*
*/
public class AppTest {
@Test
public void test() {
String[] args = {};
App.main(args);
}
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>async-method-invocation</artifactId> <artifactId>async-method-invocation</artifactId>
<dependencies> <dependencies>

View File

@ -4,23 +4,24 @@ import java.util.concurrent.Callable;
/** /**
* This application demonstrates the async method invocation pattern. Key parts of the pattern are * This application demonstrates the async method invocation pattern. Key parts of the pattern are
* <code>AsyncResult</code> which is an intermediate container for an asynchronously evaluated value, * <code>AsyncResult</code> which is an intermediate container for an asynchronously evaluated
* <code>AsyncCallback</code> which can be provided to be executed on task completion and * value, <code>AsyncCallback</code> which can be provided to be executed on task completion and
* <code>AsyncExecutor</code> that manages the execution of the async tasks. * <code>AsyncExecutor</code> that manages the execution of the async tasks.
* <p> * <p>
* The main method shows example flow of async invocations. The main thread starts multiple tasks with * The main method shows example flow of async invocations. The main thread starts multiple tasks
* variable durations and then continues its own work. When the main thread has done it's job it collects * with variable durations and then continues its own work. When the main thread has done it's job
* the results of the async tasks. Two of the tasks are handled with callbacks, meaning the callbacks are * it collects the results of the async tasks. Two of the tasks are handled with callbacks, meaning
* executed immediately when the tasks complete. * the callbacks are executed immediately when the tasks complete.
* <p> * <p>
* Noteworthy difference of thread usage between the async results and callbacks is that the async results * Noteworthy difference of thread usage between the async results and callbacks is that the async
* are collected in the main thread but the callbacks are executed within the worker threads. This should be * results are collected in the main thread but the callbacks are executed within the worker
* noted when working with thread pools. * threads. This should be noted when working with thread pools.
* <p> * <p>
* Java provides its own implementations of async method invocation pattern. FutureTask, CompletableFuture * Java provides its own implementations of async method invocation pattern. FutureTask,
* and ExecutorService are the real world implementations of this pattern. But due to the nature of parallel * CompletableFuture and ExecutorService are the real world implementations of this pattern. But due
* programming, the implementations are not trivial. This example does not take all possible scenarios into * to the nature of parallel programming, the implementations are not trivial. This example does not
* account but rather provides a simple version that helps to understand the pattern. * take all possible scenarios into account but rather provides a simple version that helps to
* understand the pattern.
* *
* @see AsyncResult * @see AsyncResult
* @see AsyncCallback * @see AsyncCallback
@ -40,8 +41,10 @@ public class App {
AsyncResult<Integer> asyncResult1 = executor.startProcess(lazyval(10, 500)); AsyncResult<Integer> asyncResult1 = executor.startProcess(lazyval(10, 500));
AsyncResult<String> asyncResult2 = executor.startProcess(lazyval("test", 300)); AsyncResult<String> asyncResult2 = executor.startProcess(lazyval("test", 300));
AsyncResult<Long> asyncResult3 = executor.startProcess(lazyval(50L, 700)); AsyncResult<Long> asyncResult3 = executor.startProcess(lazyval(50L, 700));
AsyncResult<Integer> asyncResult4 = executor.startProcess(lazyval(20, 400), callback("Callback result 4")); AsyncResult<Integer> asyncResult4 =
AsyncResult<String> asyncResult5 = executor.startProcess(lazyval("callback", 600), callback("Callback result 5")); executor.startProcess(lazyval(20, 400), callback("Callback result 4"));
AsyncResult<String> asyncResult5 =
executor.startProcess(lazyval("callback", 600), callback("Callback result 5"));
// emulate processing in the current thread while async tasks are running in their own threads // emulate processing in the current thread while async tasks are running in their own threads
Thread.sleep(350); // Oh boy I'm working hard here Thread.sleep(350); // Oh boy I'm working hard here

View File

@ -18,5 +18,4 @@ public interface AsyncCallback<T> {
* @param ex empty value if execution succeeds, some exception if executions fails * @param ex empty value if execution succeeds, some exception if executions fails
*/ */
void onComplete(T value, Optional<Exception> ex); void onComplete(T value, Optional<Exception> ex);
} }

View File

@ -38,5 +38,4 @@ public interface AsyncExecutor {
* @throws InterruptedException if the execution is interrupted * @throws InterruptedException if the execution is interrupted
*/ */
<T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException; <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;
} }

View File

@ -34,7 +34,8 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} }
@Override @Override
public <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException { public <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException,
InterruptedException {
if (asyncResult.isCompleted()) { if (asyncResult.isCompleted()) {
return asyncResult.getValue(); return asyncResult.getValue();
} else { } else {
@ -44,8 +45,8 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} }
/** /**
* Simple implementation of async result that allows completing it successfully with a value * Simple implementation of async result that allows completing it successfully with a value or
* or exceptionally with an exception. A really simplified version from its real life cousins * exceptionally with an exception. A really simplified version from its real life cousins
* FutureTask and CompletableFuture. * FutureTask and CompletableFuture.
* *
* @see java.util.concurrent.FutureTask * @see java.util.concurrent.FutureTask
@ -70,8 +71,8 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} }
/** /**
* Sets the value from successful execution and executes callback if available. Notifies * Sets the value from successful execution and executes callback if available. Notifies any
* any thread waiting for completion. * thread waiting for completion.
* *
* @param value value of the evaluated task * @param value value of the evaluated task
*/ */
@ -85,8 +86,8 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} }
/** /**
* Sets the exception from failed execution and executes callback if available. Notifies * Sets the exception from failed execution and executes callback if available. Notifies any
* any thread waiting for completion. * thread waiting for completion.
* *
* @param exception exception of the failed task * @param exception exception of the failed task
*/ */

View File

@ -14,5 +14,4 @@ public class AppTest {
String[] args = {}; String[] args = {};
App.main(args); App.main(args);
} }
} }

View File

@ -9,6 +9,8 @@ tags:
- Gang Of Four - Gang Of Four
--- ---
**Also known as:** Handle/Body
**Intent:** Decouple an abstraction from its implementation so that the two can **Intent:** Decouple an abstraction from its implementation so that the two can
vary independently. vary independently.

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>bridge</artifactId> <artifactId>bridge</artifactId>
<dependencies> <dependencies>

View File

@ -2,41 +2,38 @@ package com.iluwatar.bridge;
/** /**
* *
* The Bridge pattern can also be thought of as two layers of abstraction. With Bridge, * The Bridge pattern can also be thought of as two layers of abstraction. With Bridge, you can
* you can decouple an abstraction from its implementation so that the two can vary independently. * decouple an abstraction from its implementation so that the two can vary independently.
* <p> * <p>
* In Bridge pattern both abstraction ({@link MagicWeapon}) and implementation * In Bridge pattern both abstraction ({@link MagicWeapon}) and implementation (
* ({@link MagicWeaponImpl}) have their own class hierarchies. The interface of the * {@link MagicWeaponImpl}) have their own class hierarchies. The interface of the implementations
* implementations can be changed without affecting the clients. * can be changed without affecting the clients.
* *
*/ */
public class App { 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) { public static void main(String[] args) {
BlindingMagicWeapon blindingMagicWeapon = new BlindingMagicWeapon( BlindingMagicWeapon blindingMagicWeapon = new BlindingMagicWeapon(new Excalibur());
new Excalibur());
blindingMagicWeapon.wield(); blindingMagicWeapon.wield();
blindingMagicWeapon.blind(); blindingMagicWeapon.blind();
blindingMagicWeapon.swing(); blindingMagicWeapon.swing();
blindingMagicWeapon.unwield(); blindingMagicWeapon.unwield();
FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon( FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(new Mjollnir());
new Mjollnir());
flyingMagicWeapon.wield(); flyingMagicWeapon.wield();
flyingMagicWeapon.fly(); flyingMagicWeapon.fly();
flyingMagicWeapon.swing(); flyingMagicWeapon.swing();
flyingMagicWeapon.unwield(); flyingMagicWeapon.unwield();
SoulEatingMagicWeapon soulEatingMagicWeapon = new SoulEatingMagicWeapon( SoulEatingMagicWeapon soulEatingMagicWeapon = new SoulEatingMagicWeapon(new Stormbringer());
new Stormbringer());
soulEatingMagicWeapon.wield(); soulEatingMagicWeapon.wield();
soulEatingMagicWeapon.swing(); soulEatingMagicWeapon.swing();
soulEatingMagicWeapon.eatSoul(); soulEatingMagicWeapon.eatSoul();
soulEatingMagicWeapon.unwield(); soulEatingMagicWeapon.unwield();
} }
} }

View File

@ -34,5 +34,4 @@ public class BlindingMagicWeapon extends MagicWeapon {
public void blind() { public void blind() {
getImp().blindImp(); getImp().blindImp();
} }
} }

View File

@ -24,8 +24,6 @@ public class Excalibur extends BlindingMagicWeaponImpl {
@Override @Override
public void blindImp() { public void blindImp() {
System.out System.out.println("bright light streams from Excalibur blinding the enemy");
.println("bright light streams from Excalibur blinding the enemy");
} }
} }

View File

@ -22,5 +22,4 @@ public abstract class MagicWeapon {
public MagicWeaponImpl getImp() { public MagicWeaponImpl getImp() {
return imp; return imp;
} }
} }

View File

@ -24,8 +24,6 @@ public class Mjollnir extends FlyingMagicWeaponImpl {
@Override @Override
public void flyImp() { public void flyImp() {
System.out System.out.println("Mjollnir hits the enemy in the air and returns back to the owner's hand");
.println("Mjollnir hits the enemy in the air and returns back to the owner's hand");
} }
} }

View File

@ -26,5 +26,4 @@ public class Stormbringer extends SoulEatingMagicWeaponImpl {
public void eatSoulImp() { public void eatSoulImp() {
System.out.println("Stormbringer devours the enemy's soul"); System.out.println("Stormbringer devours the enemy's soul");
} }
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>builder</artifactId> <artifactId>builder</artifactId>
<dependencies> <dependencies>

View File

@ -1,54 +1,54 @@
package com.iluwatar.builder; package com.iluwatar.builder;
import com.iluwatar. builder.Hero.HeroBuilder; import com.iluwatar.builder.Hero.HeroBuilder;
/** /**
* *
* The intention of the Builder pattern is to find a solution to the telescoping * The intention of the Builder pattern is to find a solution to the telescoping constructor
* constructor anti-pattern. The telescoping constructor anti-pattern occurs when the * anti-pattern. The telescoping constructor anti-pattern occurs when the increase of object
* increase of object constructor parameter combination leads to an exponential list * constructor parameter combination leads to an exponential list of constructors. Instead of using
* of constructors. Instead of using numerous constructors, the builder pattern uses * numerous constructors, the builder pattern uses another object, a builder, that receives each
* another object, a builder, that receives each initialization parameter step by step * initialization parameter step by step and then returns the resulting constructed object at once.
* and then returns the resulting constructed object at once.
* <p> * <p>
* The Builder pattern has another benefit. It can be used for objects that contain * The Builder pattern has another benefit. It can be used for objects that contain flat data (html
* flat data (html code, SQL query, X.509 certificate...), that is to say, data that * code, SQL query, X.509 certificate...), that is to say, data that can't be easily edited. This
* can't be easily edited. This type of data cannot be edited step by step and must * type of data cannot be edited step by step and must be edited at once. The best way to construct
* be edited at once. The best way to construct such an object is to use a builder * such an object is to use a builder class.
* class.
* <p> * <p>
* In this example we have the Builder pattern variation as described by Joshua Bloch in * In this example we have the Builder pattern variation as described by Joshua Bloch in Effective
* Effective Java 2nd Edition. * Java 2nd Edition.
* <p> * <p>
* We want to build {@link Hero} objects, but its construction is complex because of the * We want to build {@link Hero} objects, but its construction is complex because of the many
* many parameters needed. To aid the user we introduce {@link HeroBuilder} class. * parameters needed. To aid the user we introduce {@link HeroBuilder} class. {@link HeroBuilder}
* {@link HeroBuilder} takes the minimum parameters to build {@link Hero} object in its * takes the minimum parameters to build {@link Hero} object in its constructor. After that
* constructor. After that additional configuration for the {@link Hero} object can be * additional configuration for the {@link Hero} object can be done using the fluent
* done using the fluent {@link HeroBuilder} interface. When configuration is ready the * {@link HeroBuilder} interface. When configuration is ready the build method is called to receive
* build method is called to receive the final {@link Hero} object. * the final {@link Hero} object.
* *
*/ */
public class App { 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) { public static void main(String[] args) {
Hero mage = new HeroBuilder(Profession.MAGE, "Riobard") Hero mage =
.withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER) new HeroBuilder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK)
.build(); .withWeapon(Weapon.DAGGER).build();
System.out.println(mage); System.out.println(mage);
Hero warrior = new HeroBuilder(Profession.WARRIOR, "Amberjill") Hero warrior =
.withHairColor(HairColor.BLOND) new HeroBuilder(Profession.WARRIOR, "Amberjill").withHairColor(HairColor.BLOND)
.withHairType(HairType.LONG_CURLY).withArmor(Armor.CHAIN_MAIL) .withHairType(HairType.LONG_CURLY).withArmor(Armor.CHAIN_MAIL).withWeapon(Weapon.SWORD)
.withWeapon(Weapon.SWORD).build(); .build();
System.out.println(warrior); System.out.println(warrior);
Hero thief = new HeroBuilder(Profession.THIEF, "Desmond") Hero thief =
.withHairType(HairType.BALD).withWeapon(Weapon.BOW).build(); new HeroBuilder(Profession.THIEF, "Desmond").withHairType(HairType.BALD)
.withWeapon(Weapon.BOW).build();
System.out.println(thief); System.out.println(thief);
} }

View File

@ -7,7 +7,8 @@ package com.iluwatar.builder;
*/ */
public enum HairType { public enum HairType {
BALD("bald"), SHORT("short"), CURLY("curly"), LONG_STRAIGHT("long straight"), LONG_CURLY("long curly"); BALD("bald"), SHORT("short"), CURLY("curly"), LONG_STRAIGHT("long straight"), LONG_CURLY(
"long curly");
private String title; private String title;

View File

@ -95,8 +95,7 @@ public class Hero {
public HeroBuilder(Profession profession, String name) { public HeroBuilder(Profession profession, String name) {
if (profession == null || name == null) { if (profession == null || name == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException("profession and name can not be null");
"profession and name can not be null");
} }
this.profession = profession; this.profession = profession;
this.name = name; this.name = name;

View File

@ -13,5 +13,4 @@ public enum Profession {
public String toString() { public String toString() {
return name().toLowerCase(); return name().toLowerCase();
} }
} }

View File

@ -13,5 +13,4 @@ public enum Weapon {
public String toString() { public String toString() {
return name().toLowerCase(); return name().toLowerCase();
} }
} }

View File

@ -2,7 +2,7 @@ package com.iluwatar.builder;
import org.junit.Test; import org.junit.Test;
import com.iluwatar. builder.App; import com.iluwatar.builder.App;
/** /**
* *

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>business-delegate</artifactId> <artifactId>business-delegate</artifactId>
<dependencies> <dependencies>
@ -15,5 +15,10 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,29 +1,34 @@
package com.iluwatar.business.delegate; package com.iluwatar.business.delegate;
/** /**
* The Business Delegate pattern adds an abstraction layer between the presentation and business
* tiers. By using the pattern we gain loose coupling between the tiers. The Business Delegate
* encapsulates knowledge about how to locate, connect to, and interact with the business objects
* that make up the application.
* *
* The Business Delegate pattern adds an abstraction layer between the presentation and business tiers. * <p>Some of the services the Business Delegate uses are instantiated directly, and some can be
* By using the pattern we gain loose coupling between the tiers. The Business Delegate encapsulates * retrieved through service lookups. The Business Delegate itself may contain business logic too
* knowledge about how to locate, connect to, and interact with the business objects that make up * potentially tying together multiple service calls, exception handling, retrying etc.
* the application.
* <p>
* Some of the services the Business Delegate uses are instantiated directly, and some can be retrieved
* through service lookups. The Business Delegate itself may contain business logic too potentially tying
* together multiple service calls, exception handling, retrying etc.
* <p>
* In this example the client ({@link Client}) utilizes a business delegate ({@link BusinessDelegate}) to execute a task.
* The Business Delegate then selects the appropriate service and makes the service call.
* *
* <p>In this example the client ({@link Client}) utilizes a business delegate (
* {@link BusinessDelegate}) to execute a task. The Business Delegate then selects the appropriate
* service and makes the service call.
*/ */
public class App { 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) { public static void main(String[] args) {
BusinessDelegate businessDelegate = new BusinessDelegate(); BusinessDelegate businessDelegate = new BusinessDelegate();
BusinessLookup businessLookup = new BusinessLookup();
businessLookup.setEjbService(new EjbService());
businessLookup.setJmsService(new JmsService());
businessDelegate.setLookupService(businessLookup);
businessDelegate.setServiceType(ServiceType.EJB); businessDelegate.setServiceType(ServiceType.EJB);
Client client = new Client(businessDelegate); Client client = new Client(businessDelegate);

View File

@ -1,16 +1,18 @@
package com.iluwatar.business.delegate; package com.iluwatar.business.delegate;
/** /**
*
* BusinessDelegate separates the presentation and business tiers * BusinessDelegate separates the presentation and business tiers
*
*/ */
public class BusinessDelegate { public class BusinessDelegate {
private BusinessLookup lookupService = new BusinessLookup(); private BusinessLookup lookupService;
private BusinessService businessService; private BusinessService businessService;
private ServiceType serviceType; private ServiceType serviceType;
public void setLookupService(BusinessLookup businessLookup) {
this.lookupService = businessLookup;
}
public void setServiceType(ServiceType serviceType) { public void setServiceType(ServiceType serviceType) {
this.serviceType = serviceType; this.serviceType = serviceType;
} }

View File

@ -1,17 +1,31 @@
package com.iluwatar.business.delegate; package com.iluwatar.business.delegate;
/** /**
* * Class for performing service lookups.
* Class for performing service lookups
*
*/ */
public class BusinessLookup { public class BusinessLookup {
private EjbService ejbService;
private JmsService jmsService;
/**
* @param serviceType Type of service instance to be returned.
* @return Service instance.
*/
public BusinessService getBusinessService(ServiceType serviceType) { public BusinessService getBusinessService(ServiceType serviceType) {
if (serviceType.equals(ServiceType.EJB)) { if (serviceType.equals(ServiceType.EJB)) {
return new EjbService(); return ejbService;
} else { } else {
return new JmsService(); return jmsService;
} }
} }
public void setJmsService(JmsService jmsService) {
this.jmsService = jmsService;
}
public void setEjbService(EjbService ejbService) {
this.ejbService = ejbService;
}
} }

View File

@ -1,19 +0,0 @@
package com.iluwatar.business.delegate;
import org.junit.Test;
import com.iluwatar.business.delegate.App;
/**
*
* Application test
*
*/
public class AppTest {
@Test
public void test() {
String[] args = {};
App.main(args);
}
}

View File

@ -0,0 +1,78 @@
package com.iluwatar.business.delegate;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
/**
* The Business Delegate pattern adds an abstraction layer between the presentation and business
* tiers. By using the pattern we gain loose coupling between the tiers. The Business Delegate
* encapsulates knowledge about how to locate, connect to, and interact with the business objects
* that make up the application.
*
* <p>Some of the services the Business Delegate uses are instantiated directly, and some can be
* retrieved through service lookups. The Business Delegate itself may contain business logic too
* potentially tying together multiple service calls, exception handling, retrying etc.
*/
public class BusinessDelegateTest {
private EjbService ejbService;
private JmsService jmsService;
private BusinessLookup businessLookup;
private BusinessDelegate businessDelegate;
/**
* This method sets up the instance variables of this test class. It is executed before the
* execution of every test.
*/
@Before
public void setup() {
ejbService = spy(new EjbService());
jmsService = spy(new JmsService());
businessLookup = spy(new BusinessLookup());
businessLookup.setEjbService(ejbService);
businessLookup.setJmsService(jmsService);
businessDelegate = spy(new BusinessDelegate());
businessDelegate.setLookupService(businessLookup);
}
/**
* In this example the client ({@link Client}) utilizes a business delegate (
* {@link BusinessDelegate}) to execute a task. The Business Delegate then selects the appropriate
* service and makes the service call.
*/
@Test
public void testBusinessDelegate() {
// setup a client object
Client client = new Client(businessDelegate);
// set the service type
businessDelegate.setServiceType(ServiceType.EJB);
// action
client.doTask();
// verifying that the businessDelegate was used by client during doTask() method.
verify(businessDelegate).doTask();
verify(ejbService).doProcessing();
// set the service type
businessDelegate.setServiceType(ServiceType.JMS);
// action
client.doTask();
// verifying that the businessDelegate was used by client during doTask() method.
verify(businessDelegate, times(2)).doTask();
verify(jmsService).doProcessing();
}
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>caching</artifactId> <artifactId>caching</artifactId>
<dependencies> <dependencies>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>callback</artifactId> <artifactId>callback</artifactId>
<dependencies> <dependencies>

View File

@ -2,8 +2,9 @@ package com.iluwatar.callback;
/** /**
* *
* Callback pattern is more native for functional languages where functions are treated as first-class citizens. * Callback pattern is more native for functional languages where functions are treated as
* Prior to Java 8 callbacks can be simulated using simple (alike command) interfaces. * first-class citizens. Prior to Java 8 callbacks can be simulated using simple (alike command)
* interfaces.
* *
*/ */
public class App { public class App {

View File

@ -11,5 +11,4 @@ public class SimpleTask extends Task {
public void execute() { public void execute() {
System.out.println("Perform some important activity and after call the callback method."); System.out.println("Perform some important activity and after call the callback method.");
} }
} }

View File

@ -5,8 +5,8 @@ import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
/** /**
* Add a field as a counter. Every time the callback method is called increment this * Add a field as a counter. Every time the callback method is called increment this field. Unit
* field. Unit test checks that the field is being incremented. * test checks that the field is being incremented.
* *
* Could be done with mock objects as well where the call method call is verified. * Could be done with mock objects as well where the call method call is verified.
*/ */

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>chain</artifactId> <artifactId>chain</artifactId>
<dependencies> <dependencies>

View File

@ -2,30 +2,29 @@ package com.iluwatar.chain;
/** /**
* *
* The Chain of Responsibility pattern is a design pattern consisting of command * The Chain of Responsibility pattern is a design pattern consisting of command objects and a
* objects and a series of processing objects. Each processing object contains * series of processing objects. Each processing object contains logic that defines the types of
* logic that defines the types of command objects that it can handle; the rest are * command objects that it can handle; the rest are passed to the next processing object in the
* passed to the next processing object in the chain. A mechanism also exists for * chain. A mechanism also exists for adding new processing objects to the end of this chain.
* adding new processing objects to the end of this chain.
* <p> * <p>
* In this example we organize the request handlers ({@link RequestHandler}) into a * In this example we organize the request handlers ({@link RequestHandler}) into a chain where each
* chain where each handler has a chance to act on the request on its turn. Here * handler has a chance to act on the request on its turn. Here the king ({@link OrcKing}) makes
* the king ({@link OrcKing}) makes requests and the military orcs ({@link OrcCommander}, * requests and the military orcs ({@link OrcCommander}, {@link OrcOfficer}, {@link OrcSoldier})
* {@link OrcOfficer}, {@link OrcSoldier}) form the handler chain. * form the handler chain.
* *
*/ */
public class App { 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) { public static void main(String[] args) {
OrcKing king = new OrcKing(); OrcKing king = new OrcKing();
king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle"));
king.makeRequest(new Request(RequestType.TORTURE_PRISONER, king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner"));
"torture prisoner"));
king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax"));
} }

View File

@ -9,6 +9,8 @@ tags:
- Gang Of Four - Gang Of Four
--- ---
**Also known as:** Action, Transaction
**Intent:** Encapsulate a request as an object, thereby letting you **Intent:** Encapsulate a request as an object, thereby letting you
parameterize clients with different requests, queue or log requests, and parameterize clients with different requests, queue or log requests, and
support undoable operations. support undoable operations.

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>command</artifactId> <artifactId>command</artifactId>
<dependencies> <dependencies>
@ -14,5 +14,10 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -2,21 +2,22 @@ package com.iluwatar.command;
/** /**
* *
* The Command pattern is a behavioral design pattern in which an object is used to encapsulate all information * The Command pattern is a behavioral design pattern in which an object is used to encapsulate all
* needed to perform an action or trigger an event at a later time. This information includes the method name, * information needed to perform an action or trigger an event at a later time. This information
* the object that owns the method and values for the method parameters. * includes the method name, the object that owns the method and values for the method parameters.
* <p> * <p>
* Four terms always associated with the command pattern are command, receiver, invoker and client. A command * Four terms always associated with the command pattern are command, receiver, invoker and client.
* object (spell) knows about the receiver (target) and invokes a method of the receiver. Values for parameters of * A command object (spell) knows about the receiver (target) and invokes a method of the receiver.
* the receiver method are stored in the command. The receiver then does the work. An invoker object (wizard) * Values for parameters of the receiver method are stored in the command. The receiver then does
* knows how to execute a command, and optionally does bookkeeping about the command execution. The invoker * the work. An invoker object (wizard) knows how to execute a command, and optionally does
* does not know anything about a concrete command, it knows only about command interface. Both an invoker object * bookkeeping about the command execution. The invoker does not know anything about a concrete
* and several command objects are held by a client object (app). The client decides which commands to execute at * command, it knows only about command interface. Both an invoker object and several command
* which points. To execute a command, it passes the command object to the invoker object. * objects are held by a client object (app). The client decides which commands to execute at which
* points. To execute a command, it passes the command object to the invoker object.
* <p> * <p>
* In other words, in this example the wizard casts spells on the goblin. The wizard keeps track of the previous * In other words, in this example the wizard casts spells on the goblin. The wizard keeps track of
* spells cast, so it is easy to undo them. In addition, the wizard keeps track of the spells undone, so they * the previous spells cast, so it is easy to undo them. In addition, the wizard keeps track of the
* can be redone. * spells undone, so they can be redone.
* *
* *
*/ */
@ -24,6 +25,7 @@ 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) { public static void main(String[] args) {

View File

@ -31,8 +31,8 @@ public abstract class Target {
public abstract String toString(); public abstract String toString();
public void printStatus() { public void printStatus() {
System.out.println(String.format("%s, [size=%s] [visibility=%s]", this, System.out.println(String.format("%s, [size=%s] [visibility=%s]", this, getSize(),
getSize(), getVisibility())); getVisibility()));
System.out.println(); System.out.println();
} }
} }

View File

@ -13,8 +13,7 @@ public class Wizard {
private Deque<Command> undoStack = new LinkedList<>(); private Deque<Command> undoStack = new LinkedList<>();
private Deque<Command> redoStack = new LinkedList<>(); private Deque<Command> redoStack = new LinkedList<>();
public Wizard() { public Wizard() {}
}
public void castSpell(Command command, Target target) { public void castSpell(Command command, Target target) {
System.out.println(this + " casts " + command + " at " + target); System.out.println(this + " casts " + command + " at " + target);

View File

@ -1,19 +0,0 @@
package com.iluwatar.command;
import org.junit.Test;
import com.iluwatar.command.App;
/**
*
* Application test
*
*/
public class AppTest {
@Test
public void test() {
String[] args = {};
App.main(args);
}
}

View File

@ -0,0 +1,71 @@
package com.iluwatar.command;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
* The Command pattern is a behavioral design pattern in which an object is used to encapsulate all
* information needed to perform an action or trigger an event at a later time. This information
* includes the method name, the object that owns the method and values for the method parameters.
*
* <p>Four terms always associated with the command pattern are command, receiver, invoker and
* client. A command object (spell) knows about the receiver (target) and invokes a method of
* the receiver.Values for parameters of the receiver method are stored in the command. The receiver
* then does the work. An invoker object (wizard) knows how to execute a command, and optionally
* does bookkeeping about the command execution. The invoker does not know anything about a
* concrete command, it knows only about command interface. Both an invoker object and several
* command objects are held by a client object (app). The client decides which commands to execute
* at which points. To execute a command, it passes the command object to the invoker object.
*/
public class CommandTest {
private static final String GOBLIN = "Goblin";
/**
* This test verifies that when the wizard casts spells on the goblin. The wizard keeps track of
* the previous spells cast, so it is easy to undo them. In addition, it also verifies that the
* wizard keeps track of the spells undone, so they can be redone.
*/
@Test
public void testCommand() {
Wizard wizard = new Wizard();
Goblin goblin = new Goblin();
wizard.castSpell(new ShrinkSpell(), goblin);
verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.VISIBLE);
wizard.castSpell(new InvisibilitySpell(), goblin);
verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.INVISIBLE);
wizard.undoLastSpell();
verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.VISIBLE);
wizard.undoLastSpell();
verifyGoblin(goblin, GOBLIN, Size.NORMAL, Visibility.VISIBLE);
wizard.redoLastSpell();
verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.VISIBLE);
wizard.redoLastSpell();
verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.INVISIBLE);
}
/**
* This method asserts that the passed goblin object has the name as expectedName, size as
* expectedSize and visibility as expectedVisibility.
*
* @param goblin a goblin object whose state is to be verified against other parameters
* @param expectedName expectedName of the goblin
* @param expectedSize expected size of the goblin
* @param expectedVisibilty exepcted visibility of the goblin
*/
private void verifyGoblin(Goblin goblin, String expectedName, Size expectedSize,
Visibility expectedVisibilty) {
assertEquals("Goblin's name must be same as expectedName", expectedName, goblin.toString());
assertEquals("Goblin's size must be same as expectedSize", expectedSize, goblin.getSize());
assertEquals("Goblin's visibility must be same as expectedVisibility", expectedVisibilty,
goblin.getVisibility());
}
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>composite</artifactId> <artifactId>composite</artifactId>
<dependencies> <dependencies>

View File

@ -1,20 +1,21 @@
package com.iluwatar.composite; package com.iluwatar.composite;
/** /**
* The Composite pattern is a partitioning design pattern. The Composite pattern * The Composite pattern is a partitioning design pattern. The Composite pattern describes that a
* describes that a group of objects is to be treated in the same way as a single * group of objects is to be treated in the same way as a single instance of an object. The intent
* instance of an object. The intent of a composite is to "compose" objects into * of a composite is to "compose" objects into tree structures to represent part-whole hierarchies.
* tree structures to represent part-whole hierarchies. Implementing the Composite * Implementing the Composite pattern lets clients treat individual objects and compositions
* pattern lets clients treat individual objects and compositions uniformly. * uniformly.
* <p> * <p>
* In this example we have sentences composed of words composed of letters. All of * In this example we have sentences composed of words composed of letters. All of the objects can
* the objects can be treated through the same interface ({@link LetterComposite}). * be treated through the same interface ({@link LetterComposite}).
* *
*/ */
public class App { 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) { public static void main(String[] args) {

View File

@ -22,5 +22,4 @@ public class Letter extends LetterComposite {
protected void printThisAfter() { protected void printThisAfter() {
// nop // nop
} }
} }

View File

@ -15,20 +15,19 @@ public class Messenger {
List<Word> words = new ArrayList<Word>(); List<Word> words = new ArrayList<Word>();
words.add(new Word(Arrays.asList(new Letter('W'), new Letter('h'), words.add(new Word(Arrays.asList(new Letter('W'), new Letter('h'), new Letter('e'), new Letter(
new Letter('e'), new Letter('r'), new Letter('e')))); 'r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('t'), new Letter('h'), words.add(new Word(Arrays.asList(new Letter('t'), new Letter('h'), new Letter('e'), new Letter(
new Letter('e'), new Letter('r'), new Letter('e')))); 'r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('i'), new Letter('s')))); words.add(new Word(Arrays.asList(new Letter('i'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('a')))); words.add(new Word(Arrays.asList(new Letter('a'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('h'), words.add(new Word(Arrays.asList(new Letter('w'), new Letter('h'), new Letter('i'), new Letter(
new Letter('i'), new Letter('p')))); 'p'))));
words.add(new Word(Arrays.asList(new Letter('t'), new Letter('h'), words.add(new Word(Arrays.asList(new Letter('t'), new Letter('h'), new Letter('e'), new Letter(
new Letter('e'), new Letter('r'), new Letter('e')))); 'r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('i'), new Letter('s')))); words.add(new Word(Arrays.asList(new Letter('i'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('a')))); words.add(new Word(Arrays.asList(new Letter('a'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('a'), words.add(new Word(Arrays.asList(new Letter('w'), new Letter('a'), new Letter('y'))));
new Letter('y'))));
return new Sentence(words); return new Sentence(words);
@ -38,18 +37,18 @@ public class Messenger {
List<Word> words = new ArrayList<Word>(); List<Word> words = new ArrayList<Word>();
words.add(new Word(Arrays.asList(new Letter('M'), new Letter('u'), words.add(new Word(Arrays.asList(new Letter('M'), new Letter('u'), new Letter('c'), new Letter(
new Letter('c'), new Letter('h')))); 'h'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('i'), words.add(new Word(Arrays.asList(new Letter('w'), new Letter('i'), new Letter('n'), new Letter(
new Letter('n'), new Letter('d')))); 'd'))));
words.add(new Word(Arrays.asList(new Letter('p'), new Letter('o'), words.add(new Word(Arrays.asList(new Letter('p'), new Letter('o'), new Letter('u'), new Letter(
new Letter('u'), new Letter('r'), new Letter('s')))); 'r'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('f'), new Letter('r'), words.add(new Word(Arrays.asList(new Letter('f'), new Letter('r'), new Letter('o'), new Letter(
new Letter('o'), new Letter('m')))); 'm'))));
words.add(new Word(Arrays.asList(new Letter('y'), new Letter('o'), words.add(new Word(Arrays.asList(new Letter('y'), new Letter('o'), new Letter('u'), new Letter(
new Letter('u'), new Letter('r')))); 'r'))));
words.add(new Word(Arrays.asList(new Letter('m'), new Letter('o'), words.add(new Word(Arrays.asList(new Letter('m'), new Letter('o'), new Letter('u'), new Letter(
new Letter('u'), new Letter('t'), new Letter('h')))); 't'), new Letter('h'))));
return new Sentence(words); return new Sentence(words);

View File

@ -24,5 +24,4 @@ public class Sentence extends LetterComposite {
protected void printThisAfter() { protected void printThisAfter() {
System.out.print("."); System.out.print(".");
} }
} }

View File

@ -24,5 +24,4 @@ public class Word extends LetterComposite {
protected void printThisAfter() { protected void printThisAfter() {
// nop // nop
} }
} }

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>dao</artifactId> <artifactId>dao</artifactId>
@ -21,4 +21,49 @@
<artifactId>log4j</artifactId> <artifactId>log4j</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<!--
log4j.xml file will be copied both in ${project.build.outputDirectory}
and ${project.build.directory}. Thanks to Sean Patrick Floyd
(http://stackoverflow.com/questions/5637532/maven-how-to-place-resource-file-together-with-jar)
-->
<resources>
<resource> <!-- regular processing for every resource file -->
<directory>src/main/resources</directory>
</resource>
<resource> <!-- processing with a different output directory for log4j.xml -->
<directory>src/main/resources</directory>
<includes>
<include>log4j.xml</include>
</includes>
<targetPath>..</targetPath> <!-- relative to target/classes i.e. ${project.build.directory} -->
</resource>
</resources>
<plugins>
<!--
This will exclude log4j.xml file from generated JAR
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<excludes>
<exclude>log4j.xml</exclude>
</excludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -7,14 +7,16 @@ import org.apache.log4j.Logger;
/** /**
* *
* Data Access Object (DAO) is an object that provides an abstract interface to some type of database or other * Data Access Object (DAO) is an object that provides an abstract interface to some type of
* persistence mechanism. By mapping application calls to the persistence layer, DAO provide some specific data * database or other persistence mechanism. By mapping application calls to the persistence layer,
* operations without exposing details of the database. This isolation supports the Single responsibility principle. * DAO provide some specific data operations without exposing details of the database. This
* It separates what data accesses the application needs, in terms of domain-specific objects and data types * isolation supports the Single responsibility principle. It separates what data accesses the
* (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS. * application needs, in terms of domain-specific objects and data types (the public interface of
* the DAO), from how these needs can be satisfied with a specific DBMS.
* <p> * <p>
* With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without directly * With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without
* interacting with the data. The below example demonstrates basic CRUD operations: select, add, update, and delete. * directly interacting with the data. The below example demonstrates basic CRUD operations: select,
* add, update, and delete.
* *
*/ */
public class App { public class App {

View File

@ -14,7 +14,7 @@ public class CustomerDaoImplTest {
private CustomerDaoImpl impl; private CustomerDaoImpl impl;
private List<Customer> customers; private List<Customer> customers;
private static final Customer CUSTOMER = new Customer(1, "Freddy", "Kruger"); private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger");
@Before @Before
public void setUp() { public void setUp() {

View File

@ -9,6 +9,8 @@ tags:
- Gang Of Four - Gang Of Four
--- ---
**Also known as:** Wrapper
**Intent:** Attach additional responsibilities to an object dynamically. **Intent:** Attach additional responsibilities to an object dynamically.
Decorators provide a flexible alternative to subclassing for extending Decorators provide a flexible alternative to subclassing for extending
functionality. functionality.

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>decorator</artifactId> <artifactId>decorator</artifactId>
<dependencies> <dependencies>

View File

@ -2,21 +2,21 @@ package com.iluwatar.decorator;
/** /**
* *
* The Decorator pattern is a more flexible alternative to subclassing. The Decorator * The Decorator pattern is a more flexible alternative to subclassing. The Decorator class
* class implements the same interface as the target and uses composition to * implements the same interface as the target and uses composition to "decorate" calls to the
* "decorate" calls to the target. Using the Decorator pattern it is possible to * target. Using the Decorator pattern it is possible to change the behavior of the class during
* change the behavior of the class during runtime. * runtime.
* <p> * <p>
* In this example we show how the simple {@link Troll} first attacks and then * In this example we show how the simple {@link Troll} first attacks and then flees the battle.
* flees the battle. Then we decorate the {@link Troll} with a {@link SmartTroll} * Then we decorate the {@link Troll} with a {@link SmartTroll} and perform the attack again. You
* and perform the attack again. You can see how the behavior changes after the * can see how the behavior changes after the decoration.
* decoration.
* *
*/ */
public class App { 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) { public static void main(String[] args) {

View File

@ -1,10 +1,9 @@
package com.iluwatar.decorator; package com.iluwatar.decorator;
/** /**
* SmartTroll is a decorator for {@link Hostile} objects. * SmartTroll is a decorator for {@link Hostile} objects. The calls to the {@link Hostile} interface
* The calls to the {@link Hostile} interface are intercepted * are intercepted and decorated. Finally the calls are delegated to the decorated {@link Hostile}
* and decorated. Finally the calls are delegated * object.
* to the decorated {@link Hostile} object.
* *
*/ */
public class SmartTroll implements Hostile { public class SmartTroll implements Hostile {
@ -32,5 +31,4 @@ public class SmartTroll implements Hostile {
System.out.println("The troll calls for help!"); System.out.println("The troll calls for help!");
decorated.fleeBattle(); decorated.fleeBattle();
} }
} }

View File

@ -19,5 +19,4 @@ public class Troll implements Hostile {
public void fleeBattle() { public void fleeBattle() {
System.out.println("The troll shrieks in horror and runs away!"); System.out.println("The troll shrieks in horror and runs away!");
} }
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>dependency-injection</artifactId> <artifactId>dependency-injection</artifactId>
<dependencies> <dependencies>

View File

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

View File

@ -10,27 +10,28 @@ import com.google.inject.Injector;
* - 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> * <p>
* In this example we show you three different wizards. The first one ({@link SimpleWizard}) is a naive * In this example we show you three different wizards. The first one ({@link SimpleWizard}) is a
* implementation violating the inversion of control principle. It depends directly on a concrete * naive implementation violating the inversion of control principle. It depends directly on a
* implementation which cannot be changed. * concrete implementation which cannot be changed.
* <p> * <p>
* The second wizard ({@link AdvancedWizard}) is more flexible. It does not depend on any concrete implementation * The second wizard ({@link AdvancedWizard}) is more flexible. It does not depend on any concrete
* but abstraction. It utilizes Dependency Injection pattern allowing its {@link Tobacco} dependency to be * implementation but abstraction. It utilizes Dependency Injection pattern allowing its
* injected through its constructor. This way, handling the dependency is no longer the wizard's * {@link Tobacco} dependency to be injected through its constructor. This way, handling the
* responsibility. It is resolved outside the wizard class. * dependency is no longer the wizard's responsibility. It is resolved outside the wizard class.
* <p> * <p>
* The third example takes the pattern a step further. It uses Guice framework for Dependency Injection. * The third example takes the pattern a step further. It uses Guice framework for Dependency
* {@link TobaccoModule} binds a concrete implementation to abstraction. Injector is then used to create * Injection. {@link TobaccoModule} binds a concrete implementation to abstraction. Injector is then
* {@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
*/ */
public static void main( String[] args ) { public static void main(String[] args) {
SimpleWizard simpleWizard = new SimpleWizard(); SimpleWizard simpleWizard = new SimpleWizard();
simpleWizard.smoke(); simpleWizard.smoke();

View File

@ -4,9 +4,8 @@ import javax.inject.Inject;
/** /**
* *
* GuiceWizard implements inversion of control. * GuiceWizard implements inversion of control. Its dependencies are injected through its
* Its dependencies are injected through its constructor * constructor by Guice framework.
* by Guice framework.
* *
*/ */
public class GuiceWizard implements Wizard { public class GuiceWizard implements Wizard {

View File

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

View File

@ -8,6 +8,7 @@ package com.iluwatar.dependency.injection;
public abstract class Tobacco { public abstract class Tobacco {
public void smoke(Wizard wizard) { public void smoke(Wizard wizard) {
System.out.println(String.format("%s smoking %s", wizard.getClass().getSimpleName(), this.getClass().getSimpleName())); System.out.println(String.format("%s smoking %s", wizard.getClass().getSimpleName(), this
.getClass().getSimpleName()));
} }
} }

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>double-checked-locking</artifactId> <artifactId>double-checked-locking</artifactId>
<dependencies> <dependencies>

View File

@ -6,21 +6,21 @@ import java.util.concurrent.TimeUnit;
/** /**
* *
* Double Checked Locking is a concurrency design pattern used to reduce the overhead * Double Checked Locking is a concurrency design pattern used to reduce the overhead of acquiring a
* of acquiring a lock by first testing the locking criterion (the "lock hint") without * lock by first testing the locking criterion (the "lock hint") without actually acquiring the
* actually acquiring the lock. Only if the locking criterion check indicates that * lock. Only if the locking criterion check indicates that locking is required does the actual
* locking is required does the actual locking logic proceed. * locking logic proceed.
* <p> * <p>
* In {@link Inventory} we store the items with a given size. However, we do not store * In {@link Inventory} we store the items with a given size. However, we do not store more items
* more items than the inventory size. To address concurrent access problems we * than the inventory size. To address concurrent access problems we use double checked locking to
* use double checked locking to add item to inventory. In this method, the * add item to inventory. In this method, the thread which gets the lock first adds the item.
* thread which gets the lock first adds the item.
* *
*/ */
public class App { 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) { public static void main(String[] args) {
@ -28,8 +28,7 @@ public class App {
ExecutorService executorService = Executors.newFixedThreadPool(3); ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
executorService.execute(() -> { executorService.execute(() -> {
while (inventory.addItem(new Item())) while (inventory.addItem(new Item()));
;
}); });
} }

View File

@ -28,8 +28,7 @@ public class Inventory {
try { try {
if (items.size() < inventorySize) { if (items.size() < inventorySize) {
items.add(item); items.add(item);
System.out.println(Thread.currentThread() System.out.println(Thread.currentThread() + ": items.size()=" + items.size()
+ ": items.size()=" + items.size()
+ ", inventorySize=" + inventorySize); + ", inventorySize=" + inventorySize);
return true; return true;
} }
@ -39,5 +38,4 @@ public class Inventory {
} }
return false; return false;
} }
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>double-dispatch</artifactId> <artifactId>double-dispatch</artifactId>
<dependencies> <dependencies>

View File

@ -6,20 +6,20 @@ 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 that method in the receiver. Sometimes the behaviour must also be determined * implementation of that method in the receiver. Sometimes the behaviour must also be determined by
* by the type of the parameter. * the type of the parameter.
* <p> * <p>
* One way to implement this would be to create multiple instanceof-checks for the methods parameter. * One way to implement this would be to create multiple instanceof-checks for the methods
* However, this creates a maintenance issue. When new types are added we would also need to change * parameter. However, this creates a maintenance issue. When new types are added we would also need
* the method's implementation and add a new instanceof-check. This violates the single responsibility * to change the method's implementation and add a new instanceof-check. This violates the single
* principle - a class should have only one reason to change. * responsibility principle - a class should have only one reason to change.
* <p> * <p>
* Instead of the instanceof-checks a better way is to make another virtual call on the parameter * 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 * object. This way new functionality can be easily added without the need to modify existing
* implementation (open-closed principle). * implementation (open-closed principle).
* <p> * <p>
* In this example we have hierarchy of objects ({@link GameObject}) that can collide to each other. Each * In this example we have hierarchy of objects ({@link GameObject}) that can collide to each other.
* object has its own coordinates which are checked against the other objects' coordinates. If * 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. * there is an overlap, then the objects collide utilizing the Double Dispatch pattern.
* *
*/ */
@ -27,9 +27,10 @@ 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 ) { public static void main(String[] args) {
// initialize game objects and print their status // initialize game objects and print their status
List<GameObject> objects = new ArrayList<>(); List<GameObject> objects = new ArrayList<>();
objects.add(new FlamingAsteroid(0, 0, 5, 5)); objects.add(new FlamingAsteroid(0, 0, 5, 5));
@ -40,7 +41,10 @@ public class App {
System.out.println(""); System.out.println("");
// collision check // collision check
objects.stream().forEach(o1 -> objects.stream().forEach(o2 -> { if (o1 != o2 && o1.intersectsWith(o2)) o1.collision(o2); } )); objects.stream().forEach(o1 -> objects.stream().forEach(o2 -> {
if (o1 != o2 && o1.intersectsWith(o2))
o1.collision(o2);
}));
System.out.println(""); System.out.println("");
// output eventual object statuses // output eventual object statuses

View File

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

View File

@ -18,21 +18,25 @@ public class Meteoroid extends GameObject {
@Override @Override
public void collisionResolve(FlamingAsteroid asteroid) { public void collisionResolve(FlamingAsteroid asteroid) {
System.out.println(String.format("%s hits %s.", asteroid.getClass().getSimpleName(), this.getClass().getSimpleName())); System.out.println(String.format("%s hits %s.", asteroid.getClass().getSimpleName(), this
.getClass().getSimpleName()));
} }
@Override @Override
public void collisionResolve(Meteoroid meteoroid) { public void collisionResolve(Meteoroid meteoroid) {
System.out.println(String.format("%s hits %s.", meteoroid.getClass().getSimpleName(), this.getClass().getSimpleName())); System.out.println(String.format("%s hits %s.", meteoroid.getClass().getSimpleName(), this
.getClass().getSimpleName()));
} }
@Override @Override
public void collisionResolve(SpaceStationMir mir) { public void collisionResolve(SpaceStationMir mir) {
System.out.println(String.format("%s hits %s.", mir.getClass().getSimpleName(), this.getClass().getSimpleName())); System.out.println(String.format("%s hits %s.", mir.getClass().getSimpleName(), this.getClass()
.getSimpleName()));
} }
@Override @Override
public void collisionResolve(SpaceStationIss iss) { public void collisionResolve(SpaceStationIss iss) {
System.out.println(String.format("%s hits %s.", iss.getClass().getSimpleName(), this.getClass().getSimpleName())); System.out.println(String.format("%s hits %s.", iss.getClass().getSimpleName(), this.getClass()
.getSimpleName()));
} }
} }

View File

@ -2,8 +2,7 @@ package com.iluwatar.doubledispatch;
/** /**
* *
* Rectangle has coordinates and can be checked for overlap against * Rectangle has coordinates and can be checked for overlap against other Rectangles.
* other Rectangles.
* *
*/ */
public class Rectangle { public class Rectangle {
@ -23,18 +22,22 @@ public class Rectangle {
public int getLeft() { public int getLeft() {
return left; return left;
} }
public int getTop() { public int getTop() {
return top; return top;
} }
public int getRight() { public int getRight() {
return right; return right;
} }
public int getBottom() { public int getBottom() {
return bottom; return bottom;
} }
boolean intersectsWith(Rectangle r) { boolean intersectsWith(Rectangle r) {
return !(r.getLeft() > getRight() || r.getRight() < getLeft() || r.getTop() > getBottom() || r.getBottom() < getTop()); return !(r.getLeft() > getRight() || r.getRight() < getLeft() || r.getTop() > getBottom() || r
.getBottom() < getTop());
} }
@Override @Override

View File

@ -18,34 +18,31 @@ public class SpaceStationMir extends GameObject {
@Override @Override
public void collisionResolve(FlamingAsteroid asteroid) { public void collisionResolve(FlamingAsteroid asteroid) {
System.out.println(String.format("%s hits %s. %s is damaged! %s is set on fire!", System.out.println(String.format("%s hits %s. %s is damaged! %s is set on fire!", asteroid
asteroid.getClass().getSimpleName(), this.getClass().getSimpleName(), .getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass()
this.getClass().getSimpleName(), this.getClass().getSimpleName())); .getSimpleName(), this.getClass().getSimpleName()));
setDamaged(true); setDamaged(true);
setOnFire(true); setOnFire(true);
} }
@Override @Override
public void collisionResolve(Meteoroid meteoroid) { public void collisionResolve(Meteoroid meteoroid) {
System.out.println(String.format("%s hits %s. %s is damaged!", System.out.println(String.format("%s hits %s. %s is damaged!", meteoroid.getClass()
meteoroid.getClass().getSimpleName(), this.getClass().getSimpleName(), .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) {
System.out.println(String.format("%s hits %s. %s is damaged!", System.out.println(String.format("%s hits %s. %s is damaged!", mir.getClass().getSimpleName(),
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) {
System.out.println(String.format("%s hits %s. %s is damaged!", System.out.println(String.format("%s hits %s. %s is damaged!", iss.getClass().getSimpleName(),
iss.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass().getSimpleName()));
this.getClass().getSimpleName()));
setDamaged(true); setDamaged(true);
} }
} }

View File

@ -14,9 +14,9 @@ public class RectangleTest {
@Test @Test
public void test() { public void test() {
Assert.assertTrue(new Rectangle(0,0,1,1).intersectsWith(new Rectangle(0,0,1,1))); Assert.assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(0, 0, 1, 1)));
Assert.assertTrue(new Rectangle(0,0,1,1).intersectsWith(new Rectangle(-1,-5,7,8))); Assert.assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-1, -5, 7, 8)));
Assert.assertFalse(new Rectangle(0,0,1,1).intersectsWith(new Rectangle(2,2,3,3))); Assert.assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(2, 2, 3, 3)));
Assert.assertFalse(new Rectangle(0,0,1,1).intersectsWith(new Rectangle(-2,-2,-1,-1))); Assert.assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-2, -2, -1, -1)));
} }
} }

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>event-aggregator</artifactId> <artifactId>event-aggregator</artifactId>
<dependencies> <dependencies>

View File

@ -5,22 +5,23 @@ import java.util.List;
/** /**
* *
* A system with lots of objects can lead to complexities when a client wants to subscribe * A system with lots of objects can lead to complexities when a client wants to subscribe to
* to events. The client has to find and register for each object individually, if each * events. The client has to find and register for each object individually, if each object has
* object has multiple events then each event requires a separate subscription. * multiple events then each event requires a separate subscription.
* <p> * <p>
* An Event Aggregator acts as a single source of events for many objects. It registers * An Event Aggregator acts as a single source of events for many objects. It registers for all the
* for all the events of the many objects allowing clients to register with just the aggregator. * events of the many objects allowing clients to register with just the aggregator.
* <p> * <p>
* In the example {@link LordBaelish}, {@link LordVarys} and {@link Scout} deliver events to * In the example {@link LordBaelish}, {@link LordVarys} and {@link Scout} deliver events to
* {@link KingsHand}. {@link KingsHand}, the event aggregator, then delivers the events * {@link KingsHand}. {@link KingsHand}, the event aggregator, then delivers the events to
* to {@link KingJoffrey}. * {@link KingJoffrey}.
* *
*/ */
public class App { 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) { public static void main(String[] args) {
@ -34,8 +35,8 @@ public class App {
emitters.add(new LordVarys(kingsHand)); emitters.add(new LordVarys(kingsHand));
emitters.add(new Scout(kingsHand)); emitters.add(new Scout(kingsHand));
for (Weekday day: Weekday.values()) { for (Weekday day : Weekday.values()) {
for (EventEmitter emitter: emitters) { for (EventEmitter emitter : emitters) {
emitter.timePasses(day); emitter.timePasses(day);
} }
} }

View File

@ -7,7 +7,8 @@ package com.iluwatar.event.aggregator;
*/ */
public enum Event { public enum Event {
STARK_SIGHTED("Stark sighted"), WARSHIPS_APPROACHING("Warships approaching"), TRAITOR_DETECTED("Traitor detected"); STARK_SIGHTED("Stark sighted"), WARSHIPS_APPROACHING("Warships approaching"), TRAITOR_DETECTED(
"Traitor detected");
private String description; private String description;

View File

@ -26,7 +26,7 @@ public abstract class EventEmitter {
} }
protected void notifyObservers(Event e) { protected void notifyObservers(Event e) {
for (EventObserver obs: observers) { for (EventObserver obs : observers) {
obs.onEvent(e); obs.onEvent(e);
} }
} }

View File

@ -2,8 +2,7 @@ package com.iluwatar.event.aggregator;
/** /**
* *
* KingsHand observes events from multiple sources and delivers them * KingsHand observes events from multiple sources and delivers them to listeners.
* to listeners.
* *
*/ */
public class KingsHand extends EventEmitter implements EventObserver { public class KingsHand extends EventEmitter implements EventObserver {

View File

@ -7,7 +7,8 @@ package com.iluwatar.event.aggregator;
*/ */
public enum Weekday { public enum Weekday {
MONDAY("Monday"), TUESDAY("Tuesday"), WEDNESDAY("Wednesday"), THURSDAY("Thursday"), FRIDAY("Friday"), SATURDAY("Saturday"), SUNDAY("Sunday"); MONDAY("Monday"), TUESDAY("Tuesday"), WEDNESDAY("Wednesday"), THURSDAY("Thursday"), FRIDAY(
"Friday"), SATURDAY("Saturday"), SUNDAY("Sunday");
private String description; private String description;

View File

@ -1,4 +1,5 @@
package com.iluwatar.event.aggregator; package com.iluwatar.event.aggregator;
import org.junit.Test; import org.junit.Test;
import com.iluwatar.event.aggregator.App; import com.iluwatar.event.aggregator.App;

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>execute-around</artifactId> <artifactId>execute-around</artifactId>
<dependencies> <dependencies>

View File

@ -4,23 +4,24 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
/** /**
* The Execute Around idiom specifies some code to be executed before and after * The Execute Around idiom specifies some code to be executed before and after a method. Typically
* a method. Typically the idiom is used when the API has methods to be executed in * the idiom is used when the API has methods to be executed in pairs, such as resource
* pairs, such as resource allocation/deallocation or lock acquisition/release. * allocation/deallocation or lock acquisition/release.
* <p> * <p>
* In this example, we have {@link SimpleFileWriter} class that opens and closes the file * In this example, we have {@link SimpleFileWriter} class that opens and closes the file for the
* for the user. The user specifies only what to do with the file by providing the * user. The user specifies only what to do with the file by providing the {@link FileWriterAction}
* {@link FileWriterAction} implementation. * implementation.
* *
*/ */
public class App { public class App {
/** /**
* Program entry point * Program entry point
*
* @param args command line args * @param args command line args
* @throws IOException * @throws IOException
*/ */
public static void main( String[] args ) throws IOException { public static void main(String[] args) throws IOException {
new SimpleFileWriter("testfile.txt", new FileWriterAction() { new SimpleFileWriter("testfile.txt", new FileWriterAction() {

View File

@ -5,9 +5,8 @@ import java.io.IOException;
/** /**
* *
* SimpleFileWriter handles opening and closing file for the user. The user * SimpleFileWriter handles opening and closing file for the user. The user only has to specify what
* only has to specify what to do with the file resource through {@link FileWriterAction} * to do with the file resource through {@link FileWriterAction} parameter.
* parameter.
* *
*/ */
public class SimpleFileWriter { public class SimpleFileWriter {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.iluwatar</groupId> <groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId> <artifactId>java-design-patterns</artifactId>
<version>1.7.0</version> <version>1.8.0</version>
</parent> </parent>
<artifactId>facade</artifactId> <artifactId>facade</artifactId>
<dependencies> <dependencies>

View File

@ -2,21 +2,22 @@ package com.iluwatar.facade;
/** /**
* *
* The Facade design pattern is often used when a system is very complex or difficult * The Facade design pattern is often used when a system is very complex or difficult to understand
* to understand because the system has a large number of interdependent classes or * because the system has a large number of interdependent classes or its source code is
* its source code is unavailable. This pattern hides the complexities of the larger * unavailable. This pattern hides the complexities of the larger system and provides a simpler
* system and provides a simpler interface to the client. It typically involves a single * interface to the client. It typically involves a single wrapper class which contains a set of
* wrapper class which contains a set of members required by client. These members access * members required by client. These members access the system on behalf of the facade client and
* the system on behalf of the facade client and hide the implementation details. * hide the implementation details.
* <p> * <p>
* In this example the Facade is ({@link DwarvenGoldmineFacade}) and it provides a simpler * In this example the Facade is ({@link DwarvenGoldmineFacade}) and it provides a simpler interface
* interface to the goldmine subsystem. * to the goldmine subsystem.
* *
*/ */
public class App { 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) { public static void main(String[] args) {

View File

@ -16,5 +16,4 @@ public class DwarvenCartOperator extends DwarvenMineWorker {
public String name() { public String name() {
return "Dwarf cart operator"; return "Dwarf cart operator";
} }
} }

Some files were not shown because too many files have changed in this diff Show More