Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
f018d13c39 | |||
5bec63659f | |||
9d4fff6029 | |||
092d48d150 | |||
6b99f2669e | |||
ced317bc9d | |||
e5614e5a20 | |||
012b638023 | |||
b577890db4 | |||
8ba0192864 | |||
899b9617c9 | |||
d0fca6d318 | |||
7885380633 | |||
230c02fb24 | |||
b97e9207a7 | |||
8519e13de6 | |||
ba3f583467 | |||
142274f3f7 | |||
5b06c52fff | |||
033f8e740d | |||
34528173b7 | |||
fdbfa9e8ee | |||
bf65168776 | |||
043a610754 | |||
27199325ec | |||
960b568fbb | |||
c02e65fa3a | |||
fe63c9cec4 | |||
7e4f04602e | |||
306b1f3d31 | |||
449340bd2b | |||
3af06a3a3a | |||
e7b6542134 | |||
16a8c85af6 | |||
95c16200e7 | |||
c0c21ebd91 | |||
25c1f87d46 | |||
c6ca80b25f | |||
ac5c1967df |
13
CODE_COVERAGE.md
Normal file
13
CODE_COVERAGE.md
Normal 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
|
||||||
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,5 +18,4 @@ public class OrcKingdomFactory implements KingdomFactory {
|
|||||||
public Army createArmy() {
|
public Army createArmy() {
|
||||||
return new OrcArmy();
|
return new OrcArmy();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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>
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,4 @@ package com.iluwatar.adapter;
|
|||||||
public interface Engineer {
|
public interface Engineer {
|
||||||
|
|
||||||
void operateDevice();
|
void operateDevice();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -14,5 +14,4 @@ public class AppTest {
|
|||||||
String[] args = {};
|
String[] args = {};
|
||||||
App.main(args);
|
App.main(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,5 +34,4 @@ public class BlindingMagicWeapon extends MagicWeapon {
|
|||||||
public void blind() {
|
public void blind() {
|
||||||
getImp().blindImp();
|
getImp().blindImp();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,5 +22,4 @@ public abstract class MagicWeapon {
|
|||||||
public MagicWeaponImpl getImp() {
|
public MagicWeaponImpl getImp() {
|
||||||
return imp;
|
return imp;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -4,51 +4,51 @@ 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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -13,5 +13,4 @@ public enum Profession {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return name().toLowerCase();
|
return name().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,5 +13,4 @@ public enum Weapon {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return name().toLowerCase();
|
return name().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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 {
|
||||||
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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>
|
||||||
|
@ -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"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
71
command/src/test/java/com/iluwatar/command/CommandTest.java
Normal file
71
command/src/test/java/com/iluwatar/command/CommandTest.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -22,5 +22,4 @@ public class Letter extends LetterComposite {
|
|||||||
protected void printThisAfter() {
|
protected void printThisAfter() {
|
||||||
// nop
|
// nop
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -24,5 +24,4 @@ public class Sentence extends LetterComposite {
|
|||||||
protected void printThisAfter() {
|
protected void printThisAfter() {
|
||||||
System.out.print(".");
|
System.out.print(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,5 +24,4 @@ public class Word extends LetterComposite {
|
|||||||
protected void printThisAfter() {
|
protected void printThisAfter() {
|
||||||
// nop
|
// nop
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
47
dao/pom.xml
47
dao/pom.xml
@ -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>
|
||||||
|
@ -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 {
|
||||||
|
@ -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() {
|
||||||
|
@ -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.
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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 {
|
||||||
|
@ -10,24 +10,25 @@ 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) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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()));
|
||||||
;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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,6 +27,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) {
|
||||||
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
|
@ -4,19 +4,20 @@ 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
|
||||||
*/
|
*/
|
||||||
|
@ -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 {
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -16,5 +16,4 @@ public class DwarvenCartOperator extends DwarvenMineWorker {
|
|||||||
public String name() {
|
public String name() {
|
||||||
return "Dwarf cart operator";
|
return "Dwarf cart operator";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,5 +16,4 @@ public class DwarvenGoldDigger extends DwarvenMineWorker {
|
|||||||
public String name() {
|
public String name() {
|
||||||
return "Dwarf gold digger";
|
return "Dwarf gold digger";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,10 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* DwarvenGoldmineFacade provides a single interface
|
* DwarvenGoldmineFacade provides a single interface through which users can operate the subsystems.
|
||||||
* through which users can operate the subsystems.
|
|
||||||
*
|
*
|
||||||
* This makes the goldmine easier to operate and
|
* This makes the goldmine easier to operate and cuts the dependencies from the goldmine user to the
|
||||||
* cuts the dependencies from the goldmine user to
|
* subsystems.
|
||||||
* the subsystems.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DwarvenGoldmineFacade {
|
public class DwarvenGoldmineFacade {
|
||||||
@ -37,7 +35,8 @@ public class DwarvenGoldmineFacade {
|
|||||||
makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);
|
makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeActions(Collection<DwarvenMineWorker> workers, DwarvenMineWorker.Action... actions) {
|
private void makeActions(Collection<DwarvenMineWorker> workers,
|
||||||
|
DwarvenMineWorker.Action... actions) {
|
||||||
for (DwarvenMineWorker worker : workers) {
|
for (DwarvenMineWorker worker : workers) {
|
||||||
worker.action(actions);
|
worker.action(actions);
|
||||||
}
|
}
|
||||||
|
@ -16,5 +16,4 @@ public class DwarvenTunnelDigger extends DwarvenMineWorker {
|
|||||||
public String name() {
|
public String name() {
|
||||||
return "Dwarven tunnel digger";
|
return "Dwarven tunnel digger";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ tags:
|
|||||||
- Gang Of Four
|
- Gang Of Four
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Also known as:** Virtual Constructor
|
||||||
|
|
||||||
**Intent:** Define an interface for creating an object, but let subclasses
|
**Intent:** Define an interface for creating an object, but let subclasses
|
||||||
decide which class to instantiate. Factory Method lets a class defer
|
decide which class to instantiate. Factory Method lets a class defer
|
||||||
instantiation to subclasses.
|
instantiation to subclasses.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user