Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
d149c34307 | |||
ae212dec7e | |||
d9e55c7c81 | |||
c234ee7207 | |||
c6aae59407 | |||
e3f8ef00ae | |||
74481a0267 | |||
325b68908e | |||
694a1eeafa | |||
1496a468c5 | |||
af77911a84 |
@ -1,18 +1,20 @@
|
|||||||
language: java
|
language: java
|
||||||
|
|
||||||
jdk:
|
jdk:
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- GH_REF: github.com/iluwatar/java-design-patterns.git
|
- GH_REF: github.com/iluwatar/java-design-patterns.git
|
||||||
- secure: LxTDuNS/rBWIvKkaEqr79ImZAe48mCdoYCF41coxNXgNoippo4GIBArknqtv+XvdkiuRZ1yGyj6pn8GU33c/yn+krddTUkVCwTbVatbalW5jhQjDbHYym/JcxaK9ZS/3JTeGcWrBgiPqHEEDhCf26vPZsXoMSeVCEORVKTp1BSg=
|
- secure: "LxTDuNS/rBWIvKkaEqr79ImZAe48mCdoYCF41coxNXgNoippo4GIBArknqtv+XvdkiuRZ1yGyj6pn8GU33c/yn+krddTUkVCwTbVatbalW5jhQjDbHYym/JcxaK9ZS/3JTeGcWrBgiPqHEEDhCf26vPZsXoMSeVCEORVKTp1BSg="
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- export DISPLAY=:99.0
|
- "export DISPLAY=:99.0"
|
||||||
- sh -e /etc/init.d/xvfb start
|
- "sh -e /etc/init.d/xvfb start"
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- mvn clean test jacoco:report coveralls:report
|
- mvn clean test jacoco:report coveralls:report
|
||||||
- bash update-ghpages.sh
|
- bash update-ghpages.sh
|
||||||
|
|
||||||
|
# Migration to container-based infrastructure
|
||||||
sudo: false
|
sudo: false
|
||||||
|
10
README.md
10
README.md
@ -26,13 +26,7 @@ are familiar with the patterns.
|
|||||||
Before you dive into the material, you should be familiar with various
|
Before you dive into the material, you should be familiar with various
|
||||||
[Programming/Software Design Principles](http://webpro.github.io/programming-principles/).
|
[Programming/Software Design Principles](http://webpro.github.io/programming-principles/).
|
||||||
|
|
||||||
All designs should be as simple as possible. You should start with KISS, YAGNI,
|
Once you are familiar with these concepts you can start drilling down into patterns by any of the following approaches
|
||||||
and Do The Simplest Thing That Could Possibly Work principles. Complexity and
|
|
||||||
patterns should only be introduced when they are needed for practical
|
|
||||||
extensibility.
|
|
||||||
|
|
||||||
Once you are familiar with these concepts you can start drilling down into
|
|
||||||
patterns by any of the following approaches
|
|
||||||
|
|
||||||
- Using difficulty tags, `Difficulty-Beginner`, `Difficulty-Intermediate` & `Difficulty-Expert`.
|
- Using difficulty tags, `Difficulty-Beginner`, `Difficulty-Intermediate` & `Difficulty-Expert`.
|
||||||
- Using pattern categories, `Creational`, `Behavioral` and others.
|
- Using pattern categories, `Creational`, `Behavioral` and others.
|
||||||
@ -44,6 +38,7 @@ If you are willing to contribute to the project you will find the relevant infor
|
|||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
|
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
||||||
* [Effective Java (2nd Edition)](http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683)
|
* [Effective Java (2nd Edition)](http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683)
|
||||||
* [Java Generics and Collections](http://www.amazon.com/Java-Generics-Collections-Maurice-Naftalin/dp/0596527756/)
|
* [Java Generics and Collections](http://www.amazon.com/Java-Generics-Collections-Maurice-Naftalin/dp/0596527756/)
|
||||||
* [Let's Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf)
|
* [Let's Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf)
|
||||||
@ -53,6 +48,7 @@ If you are willing to contribute to the project you will find the relevant infor
|
|||||||
* [Patterns of Enterprise Application Architecture](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)
|
* [Patterns of Enterprise Application Architecture](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)
|
||||||
* [Spring Data](http://www.amazon.com/Spring-Data-Mark-Pollack/dp/1449323952/ref=sr_1_1)
|
* [Spring Data](http://www.amazon.com/Spring-Data-Mark-Pollack/dp/1449323952/ref=sr_1_1)
|
||||||
* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2)
|
* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2)
|
||||||
|
* [Pattern Oriented Software Architecture Vol I-V](http://www.amazon.com/Pattern-Oriented-Software-Architecture-Volume-Patterns/dp/0471958697)
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
@ -4,9 +4,7 @@ title: Abstract Factory
|
|||||||
folder: abstract-factory
|
folder: abstract-factory
|
||||||
permalink: /patterns/abstract-factory/
|
permalink: /patterns/abstract-factory/
|
||||||
categories: Creational
|
categories: Creational
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Provide an interface for creating families of related or dependent
|
**Intent:** Provide an interface for creating families of related or dependent
|
||||||
@ -24,7 +22,3 @@ objects without specifying their concrete classes.
|
|||||||
**Real world examples:**
|
**Real world examples:**
|
||||||
|
|
||||||
* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)
|
* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>abstract-factory</artifactId>
|
<artifactId>abstract-factory</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,21 +3,12 @@ package com.iluwatar.abstractfactory;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Abstract Factory pattern provides a way to encapsulate a group of individual
|
|
||||||
* factories that have a common theme without specifying their concrete classes. In
|
|
||||||
* normal usage, the client software creates a concrete implementation of the abstract
|
|
||||||
* factory and then uses the generic interface of the factory to create the concrete
|
|
||||||
* objects that are part of the theme. The client does not know (or care) which
|
|
||||||
* concrete objects it gets from each of these internal factories, since it uses only
|
|
||||||
* the generic interfaces of their products. This pattern separates the details of
|
|
||||||
* implementation of a set of objects from their general usage and relies on object
|
|
||||||
* composition, as object creation is implemented in methods exposed in the factory
|
|
||||||
* interface.
|
|
||||||
* <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 its implementations ({@link ElfKingdomFactory},
|
* ({@link KingdomFactory}) and its implementations ({@link ElfKingdomFactory},
|
||||||
* {@link OrcKingdomFactory}). The example uses both concrete implementations to
|
* {@link OrcKingdomFactory}).
|
||||||
* create a king, a castle and an army.
|
* <p>
|
||||||
|
* The example uses both concrete implementations to create a king, a castle and
|
||||||
|
* an army.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
@ -7,7 +7,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
public class AppTest {
|
public class AppTest {
|
||||||
|
|
||||||
private App app = new App();
|
private App app = new App();;
|
||||||
private KingdomFactory elfFactory;
|
private KingdomFactory elfFactory;
|
||||||
private KingdomFactory orcFactory;
|
private KingdomFactory orcFactory;
|
||||||
|
|
||||||
|
@ -4,9 +4,7 @@ title: Adapter
|
|||||||
folder: adapter
|
folder: adapter
|
||||||
permalink: /patterns/adapter/
|
permalink: /patterns/adapter/
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Convert the interface of a class into another interface the clients
|
**Intent:** Convert the interface of a class into another interface the clients
|
||||||
@ -24,7 +22,3 @@ incompatible interfaces.
|
|||||||
**Real world examples:**
|
**Real world examples:**
|
||||||
|
|
||||||
* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)
|
* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>adapter</artifactId>
|
<artifactId>adapter</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,12 +2,6 @@ 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.
|
|
||||||
* <p>
|
|
||||||
* There are two variations of the Adapter pattern: The class adapter implements
|
* There are two variations of the Adapter pattern: The class adapter implements
|
||||||
* the adaptee's interface whereas the object adapter uses composition to
|
* the adaptee's interface whereas the object adapter uses composition to
|
||||||
* contain the adaptee in the adapter object. This example uses the object
|
* contain the adaptee in the adapter object. This example uses the object
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>async-method-invocation</artifactId>
|
<artifactId>async-method-invocation</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -4,9 +4,7 @@ title: Bridge
|
|||||||
folder: bridge
|
folder: bridge
|
||||||
permalink: /patterns/bridge/
|
permalink: /patterns/bridge/
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Decouple an abstraction from its implementation so that the two can
|
**Intent:** Decouple an abstraction from its implementation so that the two can
|
||||||
@ -22,7 +20,3 @@ vary independently.
|
|||||||
* changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.
|
* changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.
|
||||||
* you have a proliferation of classes. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" to refer to such class hierarchies
|
* you have a proliferation of classes. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" to refer to such class hierarchies
|
||||||
* you want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class, in which multiple objects can share the same string representation.
|
* you want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class, in which multiple objects can share the same string representation.
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>bridge</artifactId>
|
<artifactId>bridge</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,9 +2,6 @@ package com.iluwatar.bridge;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Bridge pattern can also be thought of as two layers of abstraction. With Bridge,
|
|
||||||
* you can decouple an abstraction from its implementation so that the two can vary independently.
|
|
||||||
* <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 can be changed without affecting the clients.
|
* implementations can be changed without affecting the clients.
|
||||||
|
@ -4,9 +4,7 @@ title: Builder
|
|||||||
folder: builder
|
folder: builder
|
||||||
permalink: /patterns/builder/
|
permalink: /patterns/builder/
|
||||||
categories: Creational
|
categories: Creational
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Separate the construction of a complex object from its
|
**Intent:** Separate the construction of a complex object from its
|
||||||
@ -24,7 +22,3 @@ representations.
|
|||||||
|
|
||||||
* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)
|
* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)
|
||||||
* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)
|
* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>builder</artifactId>
|
<artifactId>builder</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -4,20 +4,7 @@ import com.iluwatar. builder.Hero.HeroBuilder;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The intention of the Builder pattern is to find a solution to the telescoping
|
* This is the Builder pattern variation as described by Joshua Bloch in
|
||||||
* constructor anti-pattern. The telescoping constructor anti-pattern occurs when the
|
|
||||||
* increase of object constructor parameter combination leads to an exponential list
|
|
||||||
* of constructors. Instead of using numerous constructors, the builder pattern uses
|
|
||||||
* another object, a builder, that receives each initialization parameter step by step
|
|
||||||
* and then returns the resulting constructed object at once.
|
|
||||||
* <p>
|
|
||||||
* The Builder pattern has another benefit. It can be used for objects that contain
|
|
||||||
* flat data (html code, SQL query, X.509 certificate...), that is to say, data that
|
|
||||||
* can't be easily edited. This type of data cannot be edited step by step and must
|
|
||||||
* be edited at once. The best way to construct such an object is to use a builder
|
|
||||||
* class.
|
|
||||||
* <p>
|
|
||||||
* In this example we have the Builder pattern variation as described by Joshua Bloch in
|
|
||||||
* Effective Java 2nd Edition.
|
* Effective 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
|
||||||
|
@ -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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>business-delegate</artifactId>
|
<artifactId>business-delegate</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
1
caching/.gitignore
vendored
1
caching/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
/target/
|
|
Binary file not shown.
Before Width: | Height: | Size: 55 KiB |
@ -1,106 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
|
||||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
|
||||||
<class id="1" language="java" name="main.java.com.wssia.caching.App" project="CachingPatterns"
|
|
||||||
file="/CachingPatterns/src/main/java/com/wssia/caching/App.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="249" y="150"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</class>
|
|
||||||
<class id="2" language="java" name="main.java.com.wssia.caching.AppManager" project="CachingPatterns"
|
|
||||||
file="/CachingPatterns/src/main/java/com/wssia/caching/AppManager.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="502" y="163"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</class>
|
|
||||||
<class id="3" language="java" name="main.java.com.wssia.caching.CacheStore" project="CachingPatterns"
|
|
||||||
file="/CachingPatterns/src/main/java/com/wssia/caching/CacheStore.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="537" y="436"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</class>
|
|
||||||
<enumeration id="4" language="java" name="main.java.com.wssia.caching.CachingPolicy" project="CachingPatterns"
|
|
||||||
file="/CachingPatterns/src/main/java/com/wssia/caching/CachingPolicy.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="789" y="162"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</enumeration>
|
|
||||||
<class id="5" language="java" name="main.java.com.wssia.caching.DBManager" project="CachingPatterns"
|
|
||||||
file="/CachingPatterns/src/main/java/com/wssia/caching/DBManager.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="1137" y="134"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</class>
|
|
||||||
<class id="6" language="java" name="main.java.com.wssia.caching.LRUCache" project="CachingPatterns"
|
|
||||||
file="/CachingPatterns/src/main/java/com/wssia/caching/LRUCache.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="884" y="435"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</class>
|
|
||||||
<class id="7" language="java" name="main.java.com.wssia.caching.UserAccount" project="CachingPatterns"
|
|
||||||
file="/CachingPatterns/src/main/java/com/wssia/caching/UserAccount.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="1140" y="405"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</class>
|
|
||||||
<class id="8" language="java" name="test.java.com.wssia.caching.AppTest" project="CachingPatterns"
|
|
||||||
file="/CachingPatterns/src/test/java/com/wssia/caching/AppTest.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="251" y="374"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</class>
|
|
||||||
<association id="9">
|
|
||||||
<end type="SOURCE" refId="2" navigable="false">
|
|
||||||
<attribute id="10" name="cachingPolicy"/>
|
|
||||||
<multiplicity id="11" minimum="0" maximum="1"/>
|
|
||||||
</end>
|
|
||||||
<end type="TARGET" refId="4" navigable="true"/>
|
|
||||||
<display labels="true" multiplicity="true"/>
|
|
||||||
</association>
|
|
||||||
<association id="12">
|
|
||||||
<end type="SOURCE" refId="8" navigable="false">
|
|
||||||
<attribute id="13" name="app"/>
|
|
||||||
<multiplicity id="14" minimum="0" maximum="1"/>
|
|
||||||
</end>
|
|
||||||
<end type="TARGET" refId="1" navigable="true"/>
|
|
||||||
<display labels="true" multiplicity="true"/>
|
|
||||||
</association>
|
|
||||||
<association id="15">
|
|
||||||
<end type="SOURCE" refId="3" navigable="false">
|
|
||||||
<attribute id="16" name="cache"/>
|
|
||||||
<multiplicity id="17" minimum="0" maximum="1"/>
|
|
||||||
</end>
|
|
||||||
<end type="TARGET" refId="6" navigable="true"/>
|
|
||||||
<display labels="true" multiplicity="true"/>
|
|
||||||
</association>
|
|
||||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</classifier-display>
|
|
||||||
<association-display labels="true" multiplicity="true"/>
|
|
||||||
</class-diagram>
|
|
@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
layout: pattern
|
|
||||||
title: Caching
|
|
||||||
folder: caching
|
|
||||||
permalink: /patterns/caching/
|
|
||||||
categories: Other
|
|
||||||
tags:
|
|
||||||
- Java
|
|
||||||
---
|
|
||||||
|
|
||||||
**Intent:** To avoid expensive re-acquisition of resources by not releasing
|
|
||||||
the resources immediately after their use. The resources retain their identity, are kept in some
|
|
||||||
fast-access storage, and are re-used to avoid having to acquire them again.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
**Applicability:** Use the Caching pattern(s) when
|
|
||||||
|
|
||||||
* Repetitious acquisition, initialization, and release of the same resource causes unnecessary performance overhead.
|
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Write-through, write-around, write-back: Cache explained](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained)
|
|
||||||
* [Read-Through, Write-Through, Write-Behind, and Refresh-Ahead Caching](https://docs.oracle.com/cd/E15357_01/coh.360/e15723/cache_rtwtwbra.htm#COHDG5177)
|
|
@ -1,51 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>com.iluwatar</groupId>
|
|
||||||
<artifactId>java-design-patterns</artifactId>
|
|
||||||
<version>1.7.0</version>
|
|
||||||
</parent>
|
|
||||||
<artifactId>caching</artifactId>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>mongodb-driver</artifactId>
|
|
||||||
<version>3.0.4</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>mongodb-driver-core</artifactId>
|
|
||||||
<version>3.0.4</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>bson</artifactId>
|
|
||||||
<version>3.0.4</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<!--
|
|
||||||
Due to the use of MongoDB in the test of this pattern, TRAVIS and/or MAVEN might fail if the DB connection is
|
|
||||||
not open for the JUnit test. To avoid disrupting the compilation process, the surefire plug-in was used
|
|
||||||
to SKIP the running of the JUnit tests for this pattern. To ACTIVATE the running of the tests, change the
|
|
||||||
skipTests (below) flag to 'false' and vice-versa.
|
|
||||||
-->
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<version>2.19</version>
|
|
||||||
<configuration>
|
|
||||||
<skipTests>false</skipTests>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
|
@ -1,117 +0,0 @@
|
|||||||
package com.iluwatar.caching;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The Caching pattern describes how to avoid expensive re-acquisition of resources by not releasing
|
|
||||||
* the resources immediately after their use. The resources retain their identity, are kept in some
|
|
||||||
* fast-access storage, and are re-used to avoid having to acquire them again. There are three main
|
|
||||||
* caching strategies/techniques in this pattern; each with their own pros and cons. They are:
|
|
||||||
* <code>write-through</code> which writes data to the cache and DB in a single transaction,
|
|
||||||
* <code>write-around</code> which writes data immediately into the DB instead of the cache, and
|
|
||||||
* <code>write-behind</code> which writes data into the cache initially whilst the data is only
|
|
||||||
* written into the DB when the cache is full. The <code>read-through</code> strategy is also
|
|
||||||
* included in the mentioned three strategies -- returns data from the cache to the caller <b>if</b>
|
|
||||||
* it exists <b>else</b> queries from DB and stores it into the cache for future use. These
|
|
||||||
* strategies determine when the data in the cache should be written back to the backing store (i.e.
|
|
||||||
* Database) and help keep both data sources synchronized/up-to-date. This pattern can improve
|
|
||||||
* performance and also helps to maintain consistency between data held in the cache and the data in
|
|
||||||
* the underlying data store.
|
|
||||||
* <p>
|
|
||||||
* In this example, the user account ({@link UserAccount}) entity is used as the underlying
|
|
||||||
* application data. The cache itself is implemented as an internal (Java) data structure. It adopts
|
|
||||||
* a Least-Recently-Used (LRU) strategy for evicting data from itself when its full. The three
|
|
||||||
* strategies are individually tested. The testing of the cache is restricted towards saving and
|
|
||||||
* querying of user accounts from the underlying data store ( {@link DBManager}). The main class (
|
|
||||||
* {@link App} is not aware of the underlying mechanics of the application (i.e. save and query) and
|
|
||||||
* whether the data is coming from the cache or the DB (i.e. separation of concern). The AppManager
|
|
||||||
* ({@link AppManager}) handles the transaction of data to-and-from the underlying data store
|
|
||||||
* (depending on the preferred caching policy/strategy).
|
|
||||||
*
|
|
||||||
* <i>App --> AppManager --> CacheStore/LRUCache/CachingPolicy --> DBManager</i>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @see CacheStore
|
|
||||||
* @See LRUCache
|
|
||||||
* @see CachingPolicy
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class App {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Program entry point
|
|
||||||
*
|
|
||||||
* @param args command line args
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) {
|
|
||||||
AppManager.initDB(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
|
|
||||||
// and the App class to avoid Maven compilation errors. Set flag to
|
|
||||||
// true to run the tests with MongoDB (provided that MongoDB is
|
|
||||||
// installed and socket connection is open).
|
|
||||||
AppManager.initCacheCapacity(3);
|
|
||||||
App app = new App();
|
|
||||||
app.useReadAndWriteThroughStrategy();
|
|
||||||
app.useReadThroughAndWriteAroundStrategy();
|
|
||||||
app.useReadThroughAndWriteBehindStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read-through and write-through
|
|
||||||
*/
|
|
||||||
public void useReadAndWriteThroughStrategy() {
|
|
||||||
System.out.println("# CachingPolicy.THROUGH");
|
|
||||||
AppManager.initCachingPolicy(CachingPolicy.THROUGH);
|
|
||||||
|
|
||||||
UserAccount userAccount1 = new UserAccount("001", "John", "He is a boy.");
|
|
||||||
|
|
||||||
AppManager.save(userAccount1);
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
userAccount1 = AppManager.find("001");
|
|
||||||
userAccount1 = AppManager.find("001");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read-through and write-around
|
|
||||||
*/
|
|
||||||
public void useReadThroughAndWriteAroundStrategy() {
|
|
||||||
System.out.println("# CachingPolicy.AROUND");
|
|
||||||
AppManager.initCachingPolicy(CachingPolicy.AROUND);
|
|
||||||
|
|
||||||
UserAccount userAccount2 = new UserAccount("002", "Jane", "She is a girl.");
|
|
||||||
|
|
||||||
AppManager.save(userAccount2);
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
userAccount2 = AppManager.find("002");
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
userAccount2 = AppManager.find("002");
|
|
||||||
userAccount2.setUserName("Jane G.");
|
|
||||||
AppManager.save(userAccount2);
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
userAccount2 = AppManager.find("002");
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
userAccount2 = AppManager.find("002");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read-through and write-behind
|
|
||||||
*/
|
|
||||||
public void useReadThroughAndWriteBehindStrategy() {
|
|
||||||
System.out.println("# CachingPolicy.BEHIND");
|
|
||||||
AppManager.initCachingPolicy(CachingPolicy.BEHIND);
|
|
||||||
|
|
||||||
UserAccount userAccount3 = new UserAccount("003", "Adam", "He likes food.");
|
|
||||||
UserAccount userAccount4 = new UserAccount("004", "Rita", "She hates cats.");
|
|
||||||
UserAccount userAccount5 = new UserAccount("005", "Isaac", "He is allergic to mustard.");
|
|
||||||
|
|
||||||
AppManager.save(userAccount3);
|
|
||||||
AppManager.save(userAccount4);
|
|
||||||
AppManager.save(userAccount5);
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
userAccount3 = AppManager.find("003");
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
UserAccount userAccount6 = new UserAccount("006", "Yasha", "She is an only child.");
|
|
||||||
AppManager.save(userAccount6);
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
userAccount4 = AppManager.find("004");
|
|
||||||
System.out.println(AppManager.printCacheContent());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package com.iluwatar.caching;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* AppManager helps to bridge the gap in communication between the main class and the application's
|
|
||||||
* back-end. DB connection is initialized through this class. The chosen caching strategy/policy is
|
|
||||||
* also initialized here. Before the cache can be used, the size of the cache has to be set.
|
|
||||||
* Depending on the chosen caching policy, AppManager will call the appropriate function in the
|
|
||||||
* CacheStore class.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class AppManager {
|
|
||||||
|
|
||||||
private static CachingPolicy cachingPolicy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Developer/Tester is able to choose whether the application should use MongoDB as its underlying
|
|
||||||
* data storage or a simple Java data structure to (temporarily) store the data/objects during
|
|
||||||
* runtime.
|
|
||||||
*/
|
|
||||||
public static void initDB(boolean useMongoDB) {
|
|
||||||
if (useMongoDB) {
|
|
||||||
try {
|
|
||||||
DBManager.connect();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DBManager.createVirtualDB();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void initCachingPolicy(CachingPolicy policy) {
|
|
||||||
cachingPolicy = policy;
|
|
||||||
if (cachingPolicy == CachingPolicy.BEHIND) {
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
CacheStore.flushCache();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
CacheStore.clearCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void initCacheCapacity(int capacity) {
|
|
||||||
CacheStore.initCapacity(capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UserAccount find(String userID) {
|
|
||||||
if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) {
|
|
||||||
return CacheStore.readThrough(userID);
|
|
||||||
} else if (cachingPolicy == CachingPolicy.BEHIND) {
|
|
||||||
return CacheStore.readThroughWithWriteBackPolicy(userID);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void save(UserAccount userAccount) {
|
|
||||||
if (cachingPolicy == CachingPolicy.THROUGH) {
|
|
||||||
CacheStore.writeThrough(userAccount);
|
|
||||||
} else if (cachingPolicy == CachingPolicy.AROUND) {
|
|
||||||
CacheStore.writeAround(userAccount);
|
|
||||||
} else if (cachingPolicy == CachingPolicy.BEHIND) {
|
|
||||||
CacheStore.writeBehind(userAccount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String printCacheContent() {
|
|
||||||
return CacheStore.print();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
package com.iluwatar.caching;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The caching strategies are implemented in this class.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CacheStore {
|
|
||||||
|
|
||||||
static LRUCache cache = null;
|
|
||||||
|
|
||||||
public static void initCapacity(int capacity) {
|
|
||||||
if (null == cache)
|
|
||||||
cache = new LRUCache(capacity);
|
|
||||||
else
|
|
||||||
cache.setCapacity(capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UserAccount readThrough(String userID) {
|
|
||||||
if (cache.contains(userID)) {
|
|
||||||
System.out.println("# Cache Hit!");
|
|
||||||
return cache.get(userID);
|
|
||||||
}
|
|
||||||
System.out.println("# Cache Miss!");
|
|
||||||
UserAccount userAccount = DBManager.readFromDB(userID);
|
|
||||||
cache.set(userID, userAccount);
|
|
||||||
return userAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeThrough(UserAccount userAccount) {
|
|
||||||
if (cache.contains(userAccount.getUserID())) {
|
|
||||||
DBManager.updateDB(userAccount);
|
|
||||||
} else {
|
|
||||||
DBManager.writeToDB(userAccount);
|
|
||||||
}
|
|
||||||
cache.set(userAccount.getUserID(), userAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeAround(UserAccount userAccount) {
|
|
||||||
if (cache.contains(userAccount.getUserID())) {
|
|
||||||
DBManager.updateDB(userAccount);
|
|
||||||
cache.invalidate(userAccount.getUserID()); // Cache data has been updated -- remove older
|
|
||||||
// version from cache.
|
|
||||||
} else {
|
|
||||||
DBManager.writeToDB(userAccount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UserAccount readThroughWithWriteBackPolicy(String userID) {
|
|
||||||
if (cache.contains(userID)) {
|
|
||||||
System.out.println("# Cache Hit!");
|
|
||||||
return cache.get(userID);
|
|
||||||
}
|
|
||||||
System.out.println("# Cache Miss!");
|
|
||||||
UserAccount userAccount = DBManager.readFromDB(userID);
|
|
||||||
if (cache.isFull()) {
|
|
||||||
System.out.println("# Cache is FULL! Writing LRU data to DB...");
|
|
||||||
UserAccount toBeWrittenToDB = cache.getLRUData();
|
|
||||||
DBManager.upsertDB(toBeWrittenToDB);
|
|
||||||
}
|
|
||||||
cache.set(userID, userAccount);
|
|
||||||
return userAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeBehind(UserAccount userAccount) {
|
|
||||||
if (cache.isFull() && !cache.contains(userAccount.getUserID())) {
|
|
||||||
System.out.println("# Cache is FULL! Writing LRU data to DB...");
|
|
||||||
UserAccount toBeWrittenToDB = cache.getLRUData();
|
|
||||||
DBManager.upsertDB(toBeWrittenToDB);
|
|
||||||
}
|
|
||||||
cache.set(userAccount.getUserID(), userAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void clearCache() {
|
|
||||||
if (null != cache)
|
|
||||||
cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes remaining content in the cache into the DB.
|
|
||||||
*/
|
|
||||||
public static void flushCache() {
|
|
||||||
System.out.println("# flushCache...");
|
|
||||||
if (null == cache)
|
|
||||||
return;
|
|
||||||
ArrayList<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
|
|
||||||
for (UserAccount userAccount : listOfUserAccounts) {
|
|
||||||
DBManager.upsertDB(userAccount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String print() {
|
|
||||||
ArrayList<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("\n--CACHE CONTENT--\n");
|
|
||||||
for (UserAccount userAccount : listOfUserAccounts) {
|
|
||||||
sb.append(userAccount.toString() + "\n");
|
|
||||||
}
|
|
||||||
sb.append("----\n");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package com.iluwatar.caching;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Enum class containing the three caching strategies implemented in the pattern.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public enum CachingPolicy {
|
|
||||||
THROUGH("through"), AROUND("around"), BEHIND("behind");
|
|
||||||
|
|
||||||
private String policy;
|
|
||||||
|
|
||||||
private CachingPolicy(String policy) {
|
|
||||||
this.policy = policy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPolicy() {
|
|
||||||
return policy;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
package com.iluwatar.caching;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import org.bson.Document;
|
|
||||||
|
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
import com.mongodb.client.FindIterable;
|
|
||||||
import com.mongodb.client.MongoDatabase;
|
|
||||||
import com.mongodb.client.model.UpdateOptions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* <p>DBManager handles the communication with the underlying data store i.e. Database. It contains the
|
|
||||||
* implemented methods for querying, inserting, and updating data. MongoDB was used as the database
|
|
||||||
* for the application.</p>
|
|
||||||
*
|
|
||||||
* <p>Developer/Tester is able to choose whether the application should use MongoDB as its underlying
|
|
||||||
* data storage (connect()) or a simple Java data structure to (temporarily) store the data/objects
|
|
||||||
* during runtime (createVirtualDB()).</p>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DBManager {
|
|
||||||
|
|
||||||
private static MongoClient mongoClient;
|
|
||||||
private static MongoDatabase db;
|
|
||||||
private static boolean useMongoDB;
|
|
||||||
|
|
||||||
private static HashMap<String, UserAccount> virtualDB;
|
|
||||||
|
|
||||||
public static void createVirtualDB() {
|
|
||||||
useMongoDB = false;
|
|
||||||
virtualDB = new HashMap<String, UserAccount>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void connect() throws ParseException {
|
|
||||||
useMongoDB = true;
|
|
||||||
mongoClient = new MongoClient();
|
|
||||||
db = mongoClient.getDatabase("test");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UserAccount readFromDB(String userID) {
|
|
||||||
if (!useMongoDB) {
|
|
||||||
if (virtualDB.containsKey(userID))
|
|
||||||
return virtualDB.get(userID);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (null == db) {
|
|
||||||
try {
|
|
||||||
connect();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FindIterable<Document> iterable =
|
|
||||||
db.getCollection("user_accounts").find(new Document("userID", userID));
|
|
||||||
if (iterable == null)
|
|
||||||
return null;
|
|
||||||
Document doc = iterable.first();
|
|
||||||
UserAccount userAccount =
|
|
||||||
new UserAccount(userID, doc.getString("userName"), doc.getString("additionalInfo"));
|
|
||||||
return userAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeToDB(UserAccount userAccount) {
|
|
||||||
if (!useMongoDB) {
|
|
||||||
virtualDB.put(userAccount.getUserID(), userAccount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (null == db) {
|
|
||||||
try {
|
|
||||||
connect();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
db.getCollection("user_accounts").insertOne(
|
|
||||||
new Document("userID", userAccount.getUserID()).append("userName",
|
|
||||||
userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void updateDB(UserAccount userAccount) {
|
|
||||||
if (!useMongoDB) {
|
|
||||||
virtualDB.put(userAccount.getUserID(), userAccount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (null == db) {
|
|
||||||
try {
|
|
||||||
connect();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
db.getCollection("user_accounts").updateOne(
|
|
||||||
new Document("userID", userAccount.getUserID()),
|
|
||||||
new Document("$set", new Document("userName", userAccount.getUserName()).append(
|
|
||||||
"additionalInfo", userAccount.getAdditionalInfo())));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Insert data into DB if it does not exist. Else, update it.
|
|
||||||
*/
|
|
||||||
public static void upsertDB(UserAccount userAccount) {
|
|
||||||
if (!useMongoDB) {
|
|
||||||
virtualDB.put(userAccount.getUserID(), userAccount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (null == db) {
|
|
||||||
try {
|
|
||||||
connect();
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
db.getCollection("user_accounts").updateOne(
|
|
||||||
new Document("userID", userAccount.getUserID()),
|
|
||||||
new Document("$set", new Document("userID", userAccount.getUserID()).append("userName",
|
|
||||||
userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo())),
|
|
||||||
new UpdateOptions().upsert(true));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
package com.iluwatar.caching;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Data structure/implementation of the application's cache. The data structure consists of a hash
|
|
||||||
* table attached with a doubly linked-list. The linked-list helps in capturing and maintaining the
|
|
||||||
* LRU data in the cache. When a data is queried (from the cache), added (to the cache), or updated,
|
|
||||||
* the data is moved to the front of the list to depict itself as the most-recently-used data. The
|
|
||||||
* LRU data is always at the end of the list.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class LRUCache {
|
|
||||||
|
|
||||||
class Node {
|
|
||||||
String userID;
|
|
||||||
UserAccount userAccount;
|
|
||||||
Node previous;
|
|
||||||
Node next;
|
|
||||||
|
|
||||||
public Node(String userID, UserAccount userAccount) {
|
|
||||||
this.userID = userID;
|
|
||||||
this.userAccount = userAccount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int capacity;
|
|
||||||
HashMap<String, Node> cache = new HashMap<String, Node>();
|
|
||||||
Node head = null;
|
|
||||||
Node end = null;
|
|
||||||
|
|
||||||
public LRUCache(int capacity) {
|
|
||||||
this.capacity = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserAccount get(String userID) {
|
|
||||||
if (cache.containsKey(userID)) {
|
|
||||||
Node node = cache.get(userID);
|
|
||||||
remove(node);
|
|
||||||
setHead(node);
|
|
||||||
return node.userAccount;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Remove node from linked list.
|
|
||||||
*/
|
|
||||||
public void remove(Node node) {
|
|
||||||
if (node.previous != null) {
|
|
||||||
node.previous.next = node.next;
|
|
||||||
} else {
|
|
||||||
head = node.next;
|
|
||||||
}
|
|
||||||
if (node.next != null) {
|
|
||||||
node.next.previous = node.previous;
|
|
||||||
} else {
|
|
||||||
end = node.previous;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Move node to the front of the list.
|
|
||||||
*/
|
|
||||||
public void setHead(Node node) {
|
|
||||||
node.next = head;
|
|
||||||
node.previous = null;
|
|
||||||
if (head != null)
|
|
||||||
head.previous = node;
|
|
||||||
head = node;
|
|
||||||
if (end == null)
|
|
||||||
end = head;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(String userID, UserAccount userAccount) {
|
|
||||||
if (cache.containsKey(userID)) {
|
|
||||||
Node old = cache.get(userID);
|
|
||||||
old.userAccount = userAccount;
|
|
||||||
remove(old);
|
|
||||||
setHead(old);
|
|
||||||
} else {
|
|
||||||
Node newNode = new Node(userID, userAccount);
|
|
||||||
if (cache.size() >= capacity) {
|
|
||||||
System.out.println("# Cache is FULL! Removing " + end.userID + " from cache...");
|
|
||||||
cache.remove(end.userID); // remove LRU data from cache.
|
|
||||||
remove(end);
|
|
||||||
setHead(newNode);
|
|
||||||
} else {
|
|
||||||
setHead(newNode);
|
|
||||||
}
|
|
||||||
cache.put(userID, newNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(String userID) {
|
|
||||||
return cache.containsKey(userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate(String userID) {
|
|
||||||
System.out.println("# " + userID + " has been updated! Removing older version from cache...");
|
|
||||||
Node toBeRemoved = cache.get(userID);
|
|
||||||
remove(toBeRemoved);
|
|
||||||
cache.remove(userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFull() {
|
|
||||||
return cache.size() >= capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserAccount getLRUData() {
|
|
||||||
return end.userAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
head = null;
|
|
||||||
end = null;
|
|
||||||
cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Returns cache data in list form.
|
|
||||||
*/
|
|
||||||
public ArrayList<UserAccount> getCacheDataInListForm() {
|
|
||||||
ArrayList<UserAccount> listOfCacheData = new ArrayList<UserAccount>();
|
|
||||||
Node temp = head;
|
|
||||||
while (temp != null) {
|
|
||||||
listOfCacheData.add(temp.userAccount);
|
|
||||||
temp = temp.next;
|
|
||||||
}
|
|
||||||
return listOfCacheData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCapacity(int newCapacity) {
|
|
||||||
if (capacity > newCapacity) {
|
|
||||||
clear(); // Behavior can be modified to accommodate for decrease in cache size. For now, we'll
|
|
||||||
// just clear the cache.
|
|
||||||
} else {
|
|
||||||
this.capacity = newCapacity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package com.iluwatar.caching;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Entity class (stored in cache and DB) used in the application.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class UserAccount {
|
|
||||||
private String userID;
|
|
||||||
private String userName;
|
|
||||||
private String additionalInfo;
|
|
||||||
|
|
||||||
public UserAccount(String userID, String userName, String additionalInfo) {
|
|
||||||
this.userID = userID;
|
|
||||||
this.userName = userName;
|
|
||||||
this.additionalInfo = additionalInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUserID() {
|
|
||||||
return userID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserID(String userID) {
|
|
||||||
this.userID = userID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUserName() {
|
|
||||||
return userName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserName(String userName) {
|
|
||||||
this.userName = userName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAdditionalInfo() {
|
|
||||||
return additionalInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAdditionalInfo(String additionalInfo) {
|
|
||||||
this.additionalInfo = additionalInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return userID + ", " + userName + ", " + additionalInfo;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package com.iluwatar.caching;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Application test
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class AppTest {
|
|
||||||
App app;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup of application test includes: initializing DB connection and cache size/capacity.
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
AppManager.initDB(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
|
|
||||||
// to avoid Maven compilation errors. Set flag to true to run the
|
|
||||||
// tests with MongoDB (provided that MongoDB is installed and socket
|
|
||||||
// connection is open).
|
|
||||||
AppManager.initCacheCapacity(3);
|
|
||||||
app = new App();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReadAndWriteThroughStrategy() {
|
|
||||||
app.useReadAndWriteThroughStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReadThroughAndWriteAroundStrategy() {
|
|
||||||
app.useReadThroughAndWriteAroundStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReadThroughAndWriteBehindStrategy() {
|
|
||||||
app.useReadThroughAndWriteBehindStrategy();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>callback</artifactId>
|
<artifactId>callback</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -9,7 +9,7 @@ public class SimpleTask extends Task {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,38 +2,18 @@ package com.iluwatar.callback;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import com.iluwatar.callback.App;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a field as a counter. Every time the callback method is called increment this
|
|
||||||
* field. Unit test checks that the field is being incremented.
|
|
||||||
*
|
*
|
||||||
* Could be done with mock objects as well where the call method call is verified.
|
* Application test
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class AppTest {
|
public class AppTest {
|
||||||
|
|
||||||
private Integer callingCount = 0;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
Callback callback = new Callback() {
|
String[] args = {};
|
||||||
@Override
|
App.main(args);
|
||||||
public void call() {
|
|
||||||
callingCount++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Task task = new SimpleTask();
|
|
||||||
|
|
||||||
assertEquals("Initial calling count of 0", new Integer(0), callingCount);
|
|
||||||
|
|
||||||
task.executeWith(callback);
|
|
||||||
|
|
||||||
assertEquals("Callback called once", new Integer(1), callingCount);
|
|
||||||
|
|
||||||
task.executeWith(callback);
|
|
||||||
|
|
||||||
assertEquals("Callback called twice", new Integer(2), callingCount);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,7 @@ title: Chain of responsibility
|
|||||||
folder: chain
|
folder: chain
|
||||||
permalink: /patterns/chain/
|
permalink: /patterns/chain/
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Avoid coupling the sender of a request to its receiver by giving
|
**Intent:** Avoid coupling the sender of a request to its receiver by giving
|
||||||
@ -25,7 +23,3 @@ objects and pass the request along the chain until an object handles it.
|
|||||||
|
|
||||||
* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)
|
* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)
|
||||||
* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)
|
* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>chain</artifactId>
|
<artifactId>chain</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,16 +2,10 @@ package com.iluwatar.chain;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Chain of Responsibility pattern is a design pattern consisting of command
|
* Chain of Responsibility organizes request handlers ({@link RequestHandler}) into a
|
||||||
* objects and a series of processing objects. Each processing object contains
|
* chain where each handler has a chance to act on the request on its turn. In
|
||||||
* logic that defines the types of command objects that it can handle; the rest are
|
* this example the king ({@link OrcKing}) makes requests and the military orcs
|
||||||
* passed to the next processing object in the chain. A mechanism also exists for
|
* ({@link OrcCommander}, {@link OrcOfficer}, {@link OrcSoldier}) form the handler chain.
|
||||||
* adding new processing objects to the end of this chain.
|
|
||||||
* <p>
|
|
||||||
* In this example we organize the request handlers ({@link RequestHandler}) into a
|
|
||||||
* chain where each handler has a chance to act on the request on its turn. Here
|
|
||||||
* the king ({@link OrcKing}) makes requests and the military orcs ({@link OrcCommander},
|
|
||||||
* {@link OrcOfficer}, {@link OrcSoldier}) form the handler chain.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
@ -4,9 +4,7 @@ title: Command
|
|||||||
folder: command
|
folder: command
|
||||||
permalink: /patterns/command/
|
permalink: /patterns/command/
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Encapsulate a request as an object, thereby letting you
|
**Intent:** Encapsulate a request as an object, thereby letting you
|
||||||
@ -32,7 +30,3 @@ support undoable operations.
|
|||||||
**Real world examples:**
|
**Real world examples:**
|
||||||
|
|
||||||
* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
|
* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>command</artifactId>
|
<artifactId>command</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,9 +2,7 @@ package com.iluwatar.command;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Command pattern is a behavioral design pattern in which an object is used to encapsulate all information
|
* In Command pattern actions are objects that can be executed and undone.
|
||||||
* 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>
|
* <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. A command
|
||||||
* object (spell) knows about the receiver (target) and invokes a method of the receiver. Values for parameters of
|
* object (spell) knows about the receiver (target) and invokes a method of the receiver. Values for parameters of
|
||||||
|
@ -4,9 +4,7 @@ title: Composite
|
|||||||
folder: composite
|
folder: composite
|
||||||
permalink: /patterns/composite/
|
permalink: /patterns/composite/
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Compose objects into tree structures to represent part-whole
|
**Intent:** Compose objects into tree structures to represent part-whole
|
||||||
@ -24,7 +22,3 @@ of objects uniformly.
|
|||||||
|
|
||||||
* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)
|
* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)
|
||||||
* [Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
|
* [Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>composite</artifactId>
|
<artifactId>composite</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
package com.iluwatar.composite;
|
package com.iluwatar.composite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Composite pattern is a partitioning design pattern. The Composite pattern
|
*
|
||||||
* describes that a group of objects is to be treated in the same way as a single
|
* With Composite we can treat tree hierarchies of objects with uniform
|
||||||
* instance of an object. The intent of a composite is to "compose" objects into
|
* interface ({@link LetterComposite}). In this example we have sentences composed of
|
||||||
* tree structures to represent part-whole hierarchies. Implementing the Composite
|
* words composed of letters.
|
||||||
* pattern lets clients treat individual objects and compositions uniformly.
|
|
||||||
* <p>
|
|
||||||
* In this example we have sentences composed of words composed of letters. All of
|
|
||||||
* the objects can be treated through the same interface ({@link LetterComposite}).
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
@ -4,9 +4,7 @@ title: Data Access Object
|
|||||||
folder: dao
|
folder: dao
|
||||||
permalink: /patterns/dao/
|
permalink: /patterns/dao/
|
||||||
categories: Architectural
|
categories: Architectural
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Difficulty-Beginner
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Object provides an abstract interface to some type of database or
|
**Intent:** Object provides an abstract interface to some type of database or
|
||||||
@ -18,7 +16,3 @@ other persistence mechanism.
|
|||||||
|
|
||||||
* when you want to consolidate how the data layer is accessed
|
* when you want to consolidate how the data layer is accessed
|
||||||
* when you want to avoid writing multiple data retrieval/persistence layers
|
* when you want to avoid writing multiple data retrieval/persistence layers
|
||||||
|
|
||||||
**Credits:**
|
|
||||||
|
|
||||||
* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2)
|
|
||||||
|
@ -6,19 +6,14 @@
|
|||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>dao</artifactId>
|
<artifactId>dao</artifactId>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -3,54 +3,51 @@ package com.iluwatar.dao;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Data Access Object (DAO) is an object that provides an abstract interface to some type of database or other
|
|
||||||
* persistence mechanism. By mapping application calls to the persistence layer, DAO provide some specific data
|
|
||||||
* operations without exposing details of the database. This isolation supports the Single responsibility principle.
|
|
||||||
* It separates what data accesses the 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>
|
|
||||||
* 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 directly
|
||||||
* interacting with the data. The below example demonstrates basic CRUD operations: select, add, update, and delete.
|
* interacting with the data. The below example demonstrates basic operations(CRUD): select, add, update, and delete.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
private static Logger LOGGER = Logger.getLogger(App.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program entry point.
|
* Program entry point
|
||||||
*
|
* @param args command line args
|
||||||
* @param args command line args.
|
|
||||||
*/
|
*/
|
||||||
public static void main(final String[] args) {
|
public static void main(String[] args) {
|
||||||
final CustomerDaoImpl customerDao = new CustomerDaoImpl(generateSampleCustomers());
|
|
||||||
LOGGER.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
CustomerDaoImpl customerDao = new CustomerDaoImpl(generateSampleCustomers());
|
||||||
LOGGER.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2));
|
|
||||||
final Customer customer = new Customer(4, "Dan", "Danson");
|
System.out.println("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
||||||
|
System.out.println("customerDao.getCusterById(2): " + customerDao.getCusterById(2));
|
||||||
|
|
||||||
|
Customer customer = new Customer(4, "Dan", "Danson");
|
||||||
customerDao.addCustomer(customer);
|
customerDao.addCustomer(customer);
|
||||||
LOGGER.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
|
||||||
|
System.out.println("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
||||||
|
|
||||||
customer.setFirstName("Daniel");
|
customer.setFirstName("Daniel");
|
||||||
customer.setLastName("Danielson");
|
customer.setLastName("Danielson");
|
||||||
customerDao.updateCustomer(customer);
|
customerDao.updateCustomer(customer);
|
||||||
LOGGER.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
|
||||||
|
System.out.println("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
||||||
|
|
||||||
customerDao.deleteCustomer(customer);
|
customerDao.deleteCustomer(customer);
|
||||||
LOGGER.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
|
||||||
|
System.out.println("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate customers.
|
* Generate customers
|
||||||
*
|
* @return list of customers
|
||||||
* @return list of customers.
|
|
||||||
*/
|
*/
|
||||||
public static List<Customer> generateSampleCustomers() {
|
public static List<Customer> generateSampleCustomers() {
|
||||||
final Customer customer1 = new Customer(1, "Adam", "Adamson");
|
Customer customer1 = new Customer(1, "Adam", "Adamson");
|
||||||
final Customer customer2 = new Customer(2, "Bob", "Bobson");
|
Customer customer2 = new Customer(2, "Bob", "Bobson");
|
||||||
final Customer customer3 = new Customer(3, "Carl", "Carlson");
|
Customer customer3 = new Customer(3, "Carl", "Carlson");
|
||||||
final List<Customer> customers = new ArrayList<Customer>();
|
|
||||||
|
List<Customer> customers = new ArrayList<Customer>();
|
||||||
customers.add(customer1);
|
customers.add(customer1);
|
||||||
customers.add(customer2);
|
customers.add(customer2);
|
||||||
customers.add(customer3);
|
customers.add(customer3);
|
||||||
|
@ -11,7 +11,7 @@ public class Customer {
|
|||||||
private String firstName;
|
private String firstName;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
|
|
||||||
public Customer(final int id, final String firstName, final String lastName) {
|
public Customer(int id, String firstName, String lastName) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.firstName = firstName;
|
this.firstName = firstName;
|
||||||
this.lastName = lastName;
|
this.lastName = lastName;
|
||||||
@ -21,7 +21,7 @@ public class Customer {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(final int id) {
|
public void setId(int id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ public class Customer {
|
|||||||
return firstName;
|
return firstName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFirstName(final String firstName) {
|
public void setFirstName(String firstName) {
|
||||||
this.firstName = firstName;
|
this.firstName = firstName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,32 +37,34 @@ public class Customer {
|
|||||||
return lastName;
|
return lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastName(final String lastName) {
|
public void setLastName(String lastName) {
|
||||||
this.lastName = lastName;
|
this.lastName = lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Customer{" + "id=" + getId() + ", firstName='" + getFirstName() + '\'' + ", lastName='"
|
return "Customer{" +
|
||||||
+ getLastName() + '\'' + '}';
|
"id=" + id +
|
||||||
|
", firstName='" + firstName + '\'' +
|
||||||
|
", lastName='" + lastName + '\'' +
|
||||||
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object o) {
|
public boolean equals(Object o) {
|
||||||
boolean isEqual = false;
|
if (this == o) return true;
|
||||||
if (this == o) {
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
isEqual = true;
|
|
||||||
} else if (o != null && (getClass() == o.getClass())) {
|
Customer customer = (Customer) o;
|
||||||
final Customer customer = (Customer) o;
|
|
||||||
if (getId() == customer.getId())
|
if (id != customer.id) return false;
|
||||||
isEqual = true;
|
|
||||||
}
|
return true;
|
||||||
return isEqual;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = getId();
|
int result = id;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,13 +9,9 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface CustomerDao {
|
public interface CustomerDao {
|
||||||
|
|
||||||
List<Customer> getAllCustomers();
|
public List<Customer> getAllCustomers();
|
||||||
|
public Customer getCusterById(int id);
|
||||||
Customer getCustomerById(int id);
|
public void addCustomer(Customer customer);
|
||||||
|
public void updateCustomer(Customer customer);
|
||||||
void addCustomer(Customer customer);
|
public void deleteCustomer(Customer customer);
|
||||||
|
|
||||||
void updateCustomer(Customer customer);
|
|
||||||
|
|
||||||
void deleteCustomer(Customer customer);
|
|
||||||
}
|
}
|
@ -4,12 +4,11 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The data access object (DAO) is an object that provides an abstract interface to some type of
|
* The data access object (DAO) is an object that provides an abstract interface to some type of database or other persistence mechanism.
|
||||||
* database or other persistence mechanism. By mapping application calls to the persistence layer,
|
* By mapping application calls to the persistence layer, DAO provide some specific data operations without exposing details of the database.
|
||||||
* DAO provide some specific data operations without exposing details of the database. This
|
* This isolation supports the Single responsibility principle. It separates what data accesses the application needs, in terms of
|
||||||
* isolation supports the Single responsibility principle. It separates what data accesses the
|
* domain-specific objects and data types (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
|
* database schema, etc.
|
||||||
* the DAO), from how these needs can be satisfied with a specific DBMS, database schema, etc.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CustomerDaoImpl implements CustomerDao {
|
public class CustomerDaoImpl implements CustomerDao {
|
||||||
@ -18,7 +17,7 @@ public class CustomerDaoImpl implements CustomerDao {
|
|||||||
// Note: Normally this would be in the form of an actual database and not part of the Dao Impl.
|
// Note: Normally this would be in the form of an actual database and not part of the Dao Impl.
|
||||||
private List<Customer> customers;
|
private List<Customer> customers;
|
||||||
|
|
||||||
public CustomerDaoImpl(final List<Customer> customers) {
|
public CustomerDaoImpl(List<Customer> customers) {
|
||||||
this.customers = customers;
|
this.customers = customers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,35 +27,31 @@ public class CustomerDaoImpl implements CustomerDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Customer getCustomerById(final int id) {
|
public Customer getCusterById(int id) {
|
||||||
Customer customer = null;
|
for (int i = 0; i < customers.size(); i++) {
|
||||||
for (final Customer cus : getAllCustomers()) {
|
if (customers.get(i).getId() == id) {
|
||||||
if (cus.getId() == id) {
|
return customers.get(i);
|
||||||
customer = cus;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return customer;
|
// No customer found
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCustomer(final Customer customer) {
|
public void addCustomer(Customer customer) {
|
||||||
if (getCustomerById(customer.getId()) == null) {
|
|
||||||
customers.add(customer);
|
customers.add(customer);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateCustomer(final Customer customer) {
|
public void updateCustomer(Customer customer) {
|
||||||
if (getAllCustomers().contains(customer)) {
|
if (customers.contains(customer)) {
|
||||||
final int index = getAllCustomers().indexOf(customer);
|
customers.set(customers.indexOf(customer), customer);
|
||||||
getAllCustomers().set(index, customer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteCustomer(final Customer customer) {
|
public void deleteCustomer(Customer customer) {
|
||||||
getAllCustomers().remove(customer);
|
customers.remove(customer);
|
||||||
}
|
}
|
||||||
}
|
}
|
19
dao/src/test/java/com/iluwatar/dao/AppTest.java
Normal file
19
dao/src/test/java/com/iluwatar/dao/AppTest.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.iluwatar.dao.App;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Application test
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AppTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
String[] args = {};
|
||||||
|
App.main(args);
|
||||||
|
}
|
||||||
|
}
|
@ -1,99 +0,0 @@
|
|||||||
package com.iluwatar.dao;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class CustomerDaoImplTest {
|
|
||||||
|
|
||||||
private CustomerDaoImpl impl;
|
|
||||||
private List<Customer> customers;
|
|
||||||
private static final Customer CUSTOMER = new Customer(1, "Freddy", "Kruger");
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
customers = new ArrayList<Customer>();
|
|
||||||
customers.add(CUSTOMER);
|
|
||||||
impl = new CustomerDaoImpl(customers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void deleteExistingCustomer() {
|
|
||||||
assertEquals(1, impl.getAllCustomers().size());
|
|
||||||
impl.deleteCustomer(CUSTOMER);
|
|
||||||
assertTrue(impl.getAllCustomers().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void deleteNonExistingCustomer() {
|
|
||||||
final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
|
|
||||||
impl.deleteCustomer(nonExistingCustomer);
|
|
||||||
assertEquals(1, impl.getAllCustomers().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateExistingCustomer() {
|
|
||||||
final String newFirstname = "Bernard";
|
|
||||||
final String newLastname = "Montgomery";
|
|
||||||
final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname);
|
|
||||||
impl.updateCustomer(customer);
|
|
||||||
final Customer cust = impl.getCustomerById(CUSTOMER.getId());
|
|
||||||
assertEquals(newFirstname, cust.getFirstName());
|
|
||||||
assertEquals(newLastname, cust.getLastName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void updateNonExistingCustomer() {
|
|
||||||
final int nonExistingId = getNonExistingCustomerId();
|
|
||||||
final String newFirstname = "Douglas";
|
|
||||||
final String newLastname = "MacArthur";
|
|
||||||
final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
|
|
||||||
impl.updateCustomer(customer);
|
|
||||||
assertNull(impl.getCustomerById(nonExistingId));
|
|
||||||
final Customer existingCustomer = impl.getCustomerById(CUSTOMER.getId());
|
|
||||||
assertEquals(CUSTOMER.getFirstName(), existingCustomer.getFirstName());
|
|
||||||
assertEquals(CUSTOMER.getLastName(), existingCustomer.getLastName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void addCustomer() {
|
|
||||||
final Customer newCustomer = new Customer(3, "George", "Patton");
|
|
||||||
impl.addCustomer(newCustomer);
|
|
||||||
assertEquals(2, impl.getAllCustomers().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void addAlreadyAddedCustomer() {
|
|
||||||
final Customer newCustomer = new Customer(3, "George", "Patton");
|
|
||||||
impl.addCustomer(newCustomer);
|
|
||||||
assertEquals(2, impl.getAllCustomers().size());
|
|
||||||
impl.addCustomer(newCustomer);
|
|
||||||
assertEquals(2, impl.getAllCustomers().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getExistinCustomerById() {
|
|
||||||
assertEquals(CUSTOMER, impl.getCustomerById(CUSTOMER.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getNonExistinCustomerById() {
|
|
||||||
final int nonExistingId = getNonExistingCustomerId();
|
|
||||||
assertNull(impl.getCustomerById(nonExistingId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An arbitrary number which does not correspond to an active Customer id.
|
|
||||||
*
|
|
||||||
* @return an int of a customer id which doesn't exist
|
|
||||||
*/
|
|
||||||
private int getNonExistingCustomerId() {
|
|
||||||
return 999;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
package com.iluwatar.dao;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotEquals;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class CustomerTest {
|
|
||||||
|
|
||||||
private Customer customer;
|
|
||||||
private static final int ID = 1;
|
|
||||||
private static final String FIRSTNAME = "Winston";
|
|
||||||
private static final String LASTNAME = "Churchill";
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
customer = new Customer(ID, FIRSTNAME, LASTNAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getAndSetId() {
|
|
||||||
final int newId = 2;
|
|
||||||
customer.setId(newId);
|
|
||||||
assertEquals(newId, customer.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getAndSetFirstname() {
|
|
||||||
final String newFirstname = "Bill";
|
|
||||||
customer.setFirstName(newFirstname);
|
|
||||||
assertEquals(newFirstname, customer.getFirstName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getAndSetLastname() {
|
|
||||||
final String newLastname = "Clinton";
|
|
||||||
customer.setLastName(newLastname);
|
|
||||||
assertEquals(newLastname, customer.getLastName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void notEqualWithDifferentId() {
|
|
||||||
final int newId = 2;
|
|
||||||
final Customer otherCustomer = new Customer(newId, FIRSTNAME, LASTNAME);
|
|
||||||
assertNotEquals(customer, otherCustomer);
|
|
||||||
assertNotEquals(customer.hashCode(), otherCustomer.hashCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void equalsWithSameObjectValues() {
|
|
||||||
final Customer otherCustomer = new Customer(ID, FIRSTNAME, LASTNAME);
|
|
||||||
assertEquals(customer, otherCustomer);
|
|
||||||
assertEquals(customer.hashCode(), otherCustomer.hashCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void equalsWithSameObjects() {
|
|
||||||
assertEquals(customer, customer);
|
|
||||||
assertEquals(customer.hashCode(), customer.hashCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testToString() {
|
|
||||||
final StringBuffer buffer = new StringBuffer();
|
|
||||||
buffer.append("Customer{id=");
|
|
||||||
buffer.append("" + customer.getId());
|
|
||||||
buffer.append(", firstName='");
|
|
||||||
buffer.append(customer.getFirstName());
|
|
||||||
buffer.append("\', lastName='");
|
|
||||||
buffer.append(customer.getLastName() + "\'}");
|
|
||||||
assertEquals(buffer.toString(), customer.toString());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
|
||||||
<log4j:configuration debug="true"
|
|
||||||
xmlns:log4j='http://jakarta.apache.org/log4j/'>
|
|
||||||
|
|
||||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
|
||||||
<layout class="org.apache.log4j.PatternLayout">
|
|
||||||
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
|
|
||||||
</layout>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<level value="INFO" />
|
|
||||||
<appender-ref ref="console" />
|
|
||||||
</root>
|
|
||||||
|
|
||||||
</log4j:configuration>
|
|
@ -4,9 +4,7 @@ title: Decorator
|
|||||||
folder: decorator
|
folder: decorator
|
||||||
permalink: /patterns/decorator/
|
permalink: /patterns/decorator/
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Attach additional responsibilities to an object dynamically.
|
**Intent:** Attach additional responsibilities to an object dynamically.
|
||||||
@ -20,7 +18,3 @@ functionality.
|
|||||||
* to add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects
|
* to add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects
|
||||||
* for responsibilities that can be withdrawn
|
* for responsibilities that can be withdrawn
|
||||||
* when extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing
|
* when extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>decorator</artifactId>
|
<artifactId>decorator</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,15 +2,12 @@ package com.iluwatar.decorator;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Decorator pattern is a more flexible alternative to subclassing. The Decorator
|
* Decorator pattern is a more flexible alternative to subclassing. The decorator
|
||||||
* class implements the same interface as the target and uses composition to
|
* class implements the same interface as the target and uses composition to
|
||||||
* "decorate" calls to the target. Using the Decorator pattern it is possible to
|
* "decorate" calls to the target.
|
||||||
* change the behavior of the class during runtime.
|
|
||||||
* <p>
|
* <p>
|
||||||
* In this example we show how the simple {@link Troll} first attacks and then
|
* Using decorator pattern it is possible to change class behavior during
|
||||||
* flees the battle. Then we decorate the {@link Troll} with a {@link SmartTroll}
|
* runtime, as the example shows.
|
||||||
* and perform the attack again. You can see how the behavior changes after the
|
|
||||||
* decoration.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
@ -26,13 +23,11 @@ public class App {
|
|||||||
Hostile troll = new Troll();
|
Hostile troll = new Troll();
|
||||||
troll.attack();
|
troll.attack();
|
||||||
troll.fleeBattle();
|
troll.fleeBattle();
|
||||||
System.out.printf("Simple troll power %d.\n", troll.getAttackPower());
|
|
||||||
|
|
||||||
// change the behavior of the simple troll by adding a decorator
|
// change the behavior of the simple troll by adding a decorator
|
||||||
System.out.println("\nA smart looking troll surprises you.");
|
System.out.println("\nA smart looking troll surprises you.");
|
||||||
Hostile smart = new SmartTroll(troll);
|
Hostile smart = new SmartTroll(troll);
|
||||||
smart.attack();
|
smart.attack();
|
||||||
smart.fleeBattle();
|
smart.fleeBattle();
|
||||||
System.out.printf("Smart troll power %d.\n", smart.getAttackPower());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@ public interface Hostile {
|
|||||||
|
|
||||||
void attack();
|
void attack();
|
||||||
|
|
||||||
int getAttackPower();
|
|
||||||
|
|
||||||
void fleeBattle();
|
void fleeBattle();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,6 @@ public class SmartTroll implements Hostile {
|
|||||||
decorated.attack();
|
decorated.attack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getAttackPower() {
|
|
||||||
// decorated troll power + 20 because it is smart
|
|
||||||
return decorated.getAttackPower() + 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fleeBattle() {
|
public void fleeBattle() {
|
||||||
System.out.println("The troll calls for help!");
|
System.out.println("The troll calls for help!");
|
||||||
|
@ -11,11 +11,6 @@ public class Troll implements Hostile {
|
|||||||
System.out.println("The troll swings at you with a club!");
|
System.out.println("The troll swings at you with a club!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getAttackPower() {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
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!");
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>dependency-injection</artifactId>
|
<artifactId>dependency-injection</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>double-checked-locking</artifactId>
|
<artifactId>double-checked-locking</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,15 +2,9 @@ package com.iluwatar.doublechecked.locking;
|
|||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Double Checked Locking is a concurrency design pattern used to reduce the overhead
|
|
||||||
* of acquiring a lock by first testing the locking criterion (the "lock hint") without
|
|
||||||
* actually acquiring the lock. Only if the locking criterion check indicates that
|
|
||||||
* locking is required does the actual locking logic proceed.
|
|
||||||
* <p>
|
|
||||||
* In {@link Inventory} we store the items with a given size. However, we do not store
|
* In {@link Inventory} we store the items with a given size. However, we do not store
|
||||||
* more items than the inventory size. To address concurrent access problems we
|
* more items than the inventory size. To address concurrent access problems we
|
||||||
* use double checked locking to add item to inventory. In this method, the
|
* use double checked locking to add item to inventory. In this method, the
|
||||||
@ -27,17 +21,13 @@ public class App {
|
|||||||
final Inventory inventory = new Inventory(1000);
|
final Inventory inventory = new Inventory(1000);
|
||||||
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(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
while (inventory.addItem(new Item()))
|
while (inventory.addItem(new Item()))
|
||||||
;
|
;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
executorService.shutdown();
|
|
||||||
try {
|
|
||||||
executorService.awaitTermination(5, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
System.out.println("Error waiting for ExecutorService shutdown");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,13 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
*/
|
*/
|
||||||
public class Inventory {
|
public class Inventory {
|
||||||
|
|
||||||
private final int inventorySize;
|
private int inventorySize;
|
||||||
private final List<Item> items;
|
private List<Item> items;
|
||||||
private final Lock lock;
|
private Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
public Inventory(int inventorySize) {
|
public Inventory(int inventorySize) {
|
||||||
this.inventorySize = inventorySize;
|
this.inventorySize = inventorySize;
|
||||||
this.items = new ArrayList<>(inventorySize);
|
this.items = new ArrayList<Item>(inventorySize);
|
||||||
this.lock = new ReentrantLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addItem(Item item) {
|
public boolean addItem(Item item) {
|
||||||
@ -28,9 +27,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()
|
|
||||||
+ ", inventorySize=" + inventorySize);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>double-dispatch</artifactId>
|
<artifactId>double-dispatch</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>event-aggregator</artifactId>
|
<artifactId>event-aggregator</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -5,12 +5,8 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* A system with lots of objects can lead to complexities when a client wants to subscribe
|
* The Event Aggregator pattern channels events from multiple objects
|
||||||
* to events. The client has to find and register for each object individually, if each
|
* into a single object to simplify registration for clients.
|
||||||
* object has multiple events then each event requires a separate subscription.
|
|
||||||
* <p>
|
|
||||||
* An Event Aggregator acts as a single source of events for many objects. It registers
|
|
||||||
* for all the 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
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>execute-around</artifactId>
|
<artifactId>execute-around</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -4,9 +4,7 @@ title: Facade
|
|||||||
folder: facade
|
folder: facade
|
||||||
permalink: /patterns/facade/
|
permalink: /patterns/facade/
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Provide a unified interface to a set of interfaces in a subsystem.
|
**Intent:** Provide a unified interface to a set of interfaces in a subsystem.
|
||||||
@ -19,7 +17,3 @@ Facade defines a higher-level interface that makes the subsystem easier to use.
|
|||||||
* you want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve. Most patterns, when applied, result in more and smaller classes. This makes the subsystem more reusable and easier to customize, but it also becomes harder to use for clients that don't need to customize it. A facade can provide a simple default view of the subsystem that is good enough for most clients. Only clients needing more customizability will need to look beyond the facade.
|
* you want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve. Most patterns, when applied, result in more and smaller classes. This makes the subsystem more reusable and easier to customize, but it also becomes harder to use for clients that don't need to customize it. A facade can provide a simple default view of the subsystem that is good enough for most clients. Only clients needing more customizability will need to look beyond the facade.
|
||||||
* there are many dependencies between clients and the implementation classes of an abstraction. Introduce a facade to decouple the subsystem from clients and other subsystems, thereby promoting subsystem independence and portability.
|
* there are many dependencies between clients and the implementation classes of an abstraction. Introduce a facade to decouple the subsystem from clients and other subsystems, thereby promoting subsystem independence and portability.
|
||||||
* you want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, the you can simplify the dependencies between them by making them communicate with each other solely through their facades
|
* you want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, the you can simplify the dependencies between them by making them communicate with each other solely through their facades
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>facade</artifactId>
|
<artifactId>facade</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,15 +2,9 @@ package com.iluwatar.facade;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Facade design pattern is often used when a system is very complex or difficult
|
* Facade ({@link DwarvenGoldmineFacade}) provides simpler interface to subsystem.
|
||||||
* to understand because the system has a large number of interdependent classes or
|
|
||||||
* its source code is unavailable. This pattern hides the complexities of the larger
|
|
||||||
* system and provides a simpler interface to the client. It typically involves a single
|
|
||||||
* wrapper class which contains a set of members required by client. These members access
|
|
||||||
* the system on behalf of the facade client and hide the implementation details.
|
|
||||||
* <p>
|
* <p>
|
||||||
* In this example the Facade is ({@link DwarvenGoldmineFacade}) and it provides a simpler
|
* http://en.wikipedia.org/wiki/Facade_pattern
|
||||||
* interface to the goldmine subsystem.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
@ -7,7 +7,6 @@ categories: Creational
|
|||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
- Difficulty-Beginner
|
- Difficulty-Beginner
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Define an interface for creating an object, but let subclasses
|
**Intent:** Define an interface for creating an object, but let subclasses
|
||||||
@ -21,7 +20,3 @@ instantiation to subclasses.
|
|||||||
* a class can't anticipate the class of objects it must create
|
* a class can't anticipate the class of objects it must create
|
||||||
* a class wants its subclasses to specify the objects it creates
|
* a class wants its subclasses to specify the objects it creates
|
||||||
* classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate
|
* classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>factory-method</artifactId>
|
<artifactId>factory-method</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,14 +2,7 @@ package com.iluwatar.factory.method;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Factory Method is a creational design pattern which uses factory methods to deal
|
* In Factory Method we have an interface ({@link Blacksmith}) with a method for
|
||||||
* with the problem of creating objects without specifying the exact class of object
|
|
||||||
* that will be created. This is done by creating objects via calling a factory
|
|
||||||
* method either specified in an interface and implemented by child classes, or implemented
|
|
||||||
* in a base class and optionally overridden by derived classes—rather than by calling a
|
|
||||||
* constructor.
|
|
||||||
* <p>
|
|
||||||
* In this Factory Method example we have an interface ({@link Blacksmith}) with a method for
|
|
||||||
* creating objects ({@link Blacksmith#manufactureWeapon}). The concrete subclasses
|
* creating objects ({@link Blacksmith#manufactureWeapon}). The concrete subclasses
|
||||||
* ({@link OrcBlacksmith}, {@link ElfBlacksmith}) then override the method to produce
|
* ({@link OrcBlacksmith}, {@link ElfBlacksmith}) then override the method to produce
|
||||||
* objects of their liking.
|
* objects of their liking.
|
||||||
|
@ -32,10 +32,10 @@
|
|||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
</display>
|
</display>
|
||||||
</class>
|
</class>
|
||||||
<interface id="4" language="java" name="com.iluwatar.fluentinterface.fluentiterable.FluentIterable"
|
<interface id="4" language="java" name="com.iluwatar.fluentinterface.fluentiterable.core.FluentIterable"
|
||||||
project="fluentinterface"
|
project="fluentinterface"
|
||||||
file="/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java" binary="false"
|
file="/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/core/FluentIterable.java"
|
||||||
corner="BOTTOM_RIGHT">
|
binary="false" corner="BOTTOM_RIGHT">
|
||||||
<position height="-1" width="-1" x="794" y="55"/>
|
<position height="-1" width="-1" x="794" y="55"/>
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
sort-features="false" accessors="true" visibility="true">
|
sort-features="false" accessors="true" visibility="true">
|
||||||
@ -64,16 +64,16 @@
|
|||||||
</display>
|
</display>
|
||||||
</interface>
|
</interface>
|
||||||
<dependency id="7">
|
<dependency id="7">
|
||||||
<end type="SOURCE" refId="3"/>
|
<end type="SOURCE" refId="1"/>
|
||||||
<end type="TARGET" refId="5"/>
|
<end type="TARGET" refId="4"/>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency id="8">
|
<dependency id="8">
|
||||||
<end type="SOURCE" refId="1"/>
|
<end type="SOURCE" refId="1"/>
|
||||||
<end type="TARGET" refId="3"/>
|
<end type="TARGET" refId="3"/>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency id="9">
|
<dependency id="9">
|
||||||
<end type="SOURCE" refId="1"/>
|
<end type="SOURCE" refId="3"/>
|
||||||
<end type="TARGET" refId="4"/>
|
<end type="TARGET" refId="5"/>
|
||||||
</dependency>
|
</dependency>
|
||||||
<realization id="10">
|
<realization id="10">
|
||||||
<end type="SOURCE" refId="2"/>
|
<end type="SOURCE" refId="2"/>
|
||||||
@ -83,14 +83,14 @@
|
|||||||
<end type="SOURCE" refId="3"/>
|
<end type="SOURCE" refId="3"/>
|
||||||
<end type="TARGET" refId="4"/>
|
<end type="TARGET" refId="4"/>
|
||||||
</realization>
|
</realization>
|
||||||
<dependency id="12">
|
<generalization id="12">
|
||||||
<end type="SOURCE" refId="1"/>
|
|
||||||
<end type="TARGET" refId="2"/>
|
|
||||||
</dependency>
|
|
||||||
<generalization id="13">
|
|
||||||
<end type="SOURCE" refId="4"/>
|
<end type="SOURCE" refId="4"/>
|
||||||
<end type="TARGET" refId="6"/>
|
<end type="TARGET" refId="6"/>
|
||||||
</generalization>
|
</generalization>
|
||||||
|
<dependency id="13">
|
||||||
|
<end type="SOURCE" refId="1"/>
|
||||||
|
<end type="TARGET" refId="2"/>
|
||||||
|
</dependency>
|
||||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="true" signature="true"
|
<classifier-display autosize="true" stereotype="true" package="true" initial-value="true" signature="true"
|
||||||
sort-features="false" accessors="true" visibility="true">
|
sort-features="false" accessors="true" visibility="true">
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.7.0</version>
|
<version>1.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.iluwatar.fluentinterface.app;
|
package com.iluwatar.fluentinterface.app;
|
||||||
|
|
||||||
import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
|
import com.iluwatar.fluentinterface.fluentiterable.core.FluentIterable;
|
||||||
import com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable;
|
import com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable;
|
||||||
import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable;
|
import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable;
|
||||||
|
|
||||||
@ -11,14 +11,15 @@ import java.util.function.Predicate;
|
|||||||
import static java.lang.String.valueOf;
|
import static java.lang.String.valueOf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API. Those
|
* Fluent interface pattern is useful when you want to provide an easy readable, flowing API. Those
|
||||||
* interfaces tend to mimic domain specific languages, so they can nearly be read as human languages.
|
* interfaces tend to mimic domain specific languages, so they can nearly be read as human
|
||||||
|
* languages.
|
||||||
* <p>
|
* <p>
|
||||||
* In this example two implementations of a {@link FluentIterable} interface are given. The
|
* In this example two implementations of a {@link FluentIterable} interface are given. The
|
||||||
* {@link SimpleFluentIterable} evaluates eagerly and would be too costly for real world applications.
|
* SimpleFluentIterable evaluates eagerly and would be too costly for real world applications. The
|
||||||
* The {@link LazyFluentIterable} is evaluated on termination. Their usage is demonstrated with a
|
* LazyFluentIterable is evaluated on termination. Their usage is demonstrated with a simple number
|
||||||
* simple number list that is filtered, transformed and collected. The result is printed afterwards.
|
* list that is filtered, transformed and collected. The result is printed afterwards.
|
||||||
*
|
* <p>
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.iluwatar.fluentinterface.fluentiterable;
|
package com.iluwatar.fluentinterface.fluentiterable.core;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
@ -7,7 +7,7 @@ import java.util.Optional;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
|
import com.iluwatar.fluentinterface.fluentiterable.core.FluentIterable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a lazy implementation of the FluentIterable interface. It evaluates all chained
|
* This is a lazy implementation of the FluentIterable interface. It evaluates all chained
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package com.iluwatar.fluentinterface.fluentiterable.simple;
|
package com.iluwatar.fluentinterface.fluentiterable.simple;
|
||||||
|
|
||||||
import com.iluwatar.fluentinterface.fluentiterable.FluentIterable;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.iluwatar.fluentinterface.fluentiterable.core.FluentIterable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a simple implementation of the FluentIterable interface. It evaluates all chained
|
* This is a simple implementation of the FluentIterable interface. It evaluates all chained
|
||||||
* operations eagerly. This implementation would be costly to be utilized in real applications.
|
* operations eagerly. This implementation would be costly to be utilized in real applications.
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>flux</artifactId>
|
<artifactId>flux</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -4,9 +4,7 @@ title: Flyweight
|
|||||||
folder: flyweight
|
folder: flyweight
|
||||||
permalink: /patterns/flyweight/
|
permalink: /patterns/flyweight/
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Use sharing to support large numbers of fine-grained objects
|
**Intent:** Use sharing to support large numbers of fine-grained objects
|
||||||
@ -27,7 +25,3 @@ true
|
|||||||
**Real world examples:**
|
**Real world examples:**
|
||||||
|
|
||||||
* [java.lang.Integer#valueOf(int)](http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf%28int%29)
|
* [java.lang.Integer#valueOf(int)](http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf%28int%29)
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>flyweight</artifactId>
|
<artifactId>flyweight</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -22,9 +22,3 @@ internationalization, routing and logging in a single place.
|
|||||||
**Real world examples:**
|
**Real world examples:**
|
||||||
|
|
||||||
* [Apache Struts](https://struts.apache.org/)
|
* [Apache Struts](https://struts.apache.org/)
|
||||||
|
|
||||||
**Credits:**
|
|
||||||
|
|
||||||
* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2)
|
|
||||||
* [Presentation Tier Patterns](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns)
|
|
||||||
* [Patterns of Enterprise Application Architecture](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)
|
|
||||||
|
@ -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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>front-controller</artifactId>
|
<artifactId>front-controller</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -30,4 +30,3 @@ degrading execution efficiency.
|
|||||||
**Credits:**
|
**Credits:**
|
||||||
|
|
||||||
* [Douglas C. Schmidt and Charles D. Cranor - Half Sync/Half Async](http://www.cs.wustl.edu/~schmidt/PDF/PLoP-95.pdf)
|
* [Douglas C. Schmidt and Charles D. Cranor - Half Sync/Half Async](http://www.cs.wustl.edu/~schmidt/PDF/PLoP-95.pdf)
|
||||||
* [Pattern Oriented Software Architecture Vol I-V](http://www.amazon.com/Pattern-Oriented-Software-Architecture-Volume-Patterns/dp/0471958697)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>half-sync-half-async</artifactId>
|
<artifactId>half-sync-half-async</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -18,11 +18,6 @@ post-processing to requests from a client to a target
|
|||||||
* a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers
|
* a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers
|
||||||
* you want a modular approach to configuring pre-processing and post-processing schemes
|
* you want a modular approach to configuring pre-processing and post-processing schemes
|
||||||
|
|
||||||
**Real world examples:**
|
|
||||||
|
|
||||||
* [Struts 2 - Interceptors](https://struts.apache.org/docs/interceptors.html)
|
|
||||||
|
|
||||||
**Credits:**
|
**Credits:**
|
||||||
|
|
||||||
* [TutorialsPoint - Intercepting Filter](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm)
|
* [TutorialsPoint - Intercepting Filter](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm)
|
||||||
* [Presentation Tier Patterns](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>intercepting-filter</artifactId>
|
<artifactId>intercepting-filter</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,32 +2,8 @@ package com.iluwatar.intercepting.filter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* When a request enters a Web application, it often must pass several entrance
|
* This is an app that checks whether the order request is valid through pre-processing done via {@link Filter}.
|
||||||
* tests prior to the main processing stage. For example,
|
* Each field has its own corresponding {@link Filter}
|
||||||
* - Has the client been authenticated?
|
|
||||||
* - Does the client have a valid session?
|
|
||||||
* - Is the client's IP address from a trusted network?
|
|
||||||
* - Does the request path violate any constraints?
|
|
||||||
* - What encoding does the client use to send the data?
|
|
||||||
* - Do we support the browser type of the client?
|
|
||||||
* Some of these checks are tests, resulting in a yes or no answer that determines
|
|
||||||
* whether processing will continue. Other checks manipulate the incoming data
|
|
||||||
* stream into a form suitable for processing.
|
|
||||||
* <p>
|
|
||||||
* The classic solution consists of a series of conditional checks, with any failed
|
|
||||||
* check aborting the request. Nested if/else statements are a standard strategy,
|
|
||||||
* but this solution leads to code fragility and a copy-and-paste style of programming,
|
|
||||||
* because the flow of the filtering and the action of the filters is compiled into
|
|
||||||
* the application.
|
|
||||||
* <p>
|
|
||||||
* The key to solving this problem in a flexible and unobtrusive manner is to have a
|
|
||||||
* simple mechanism for adding and removing processing components, in which each
|
|
||||||
* component completes a specific filtering action. This is the Intercepting Filter
|
|
||||||
* pattern in action.
|
|
||||||
* <p>
|
|
||||||
* In this example we check whether the order request is valid through pre-processing
|
|
||||||
* done via {@link Filter}. Each field has its own corresponding {@link Filter}
|
|
||||||
* <p>
|
|
||||||
* @author joshzambales
|
* @author joshzambales
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -4,9 +4,7 @@ title: Interpreter
|
|||||||
folder: interpreter
|
folder: interpreter
|
||||||
permalink: /patterns/interpreter/
|
permalink: /patterns/interpreter/
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Given a language, define a representation for its grammar along
|
**Intent:** Given a language, define a representation for its grammar along
|
||||||
@ -21,7 +19,3 @@ trees. The Interpreter pattern works best when
|
|||||||
|
|
||||||
* the grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time
|
* the grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time
|
||||||
* efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, the translator can be implemented by the Interpreter pattern, so the pattern is still applicable
|
* efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, the translator can be implemented by the Interpreter pattern, so the pattern is still applicable
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>interpreter</artifactId>
|
<artifactId>interpreter</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -4,14 +4,8 @@ import java.util.Stack;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Interpreter pattern is a design pattern that specifies how to evaluate sentences
|
* Interpreter pattern breaks sentences into expressions ({@link Expression}) that can
|
||||||
* in a language. The basic idea is to have a class for each symbol (terminal or nonterminal)
|
* be evaluated and as a whole form the result.
|
||||||
* in a specialized computer language. The syntax tree of a sentence in the language is an
|
|
||||||
* instance of the composite pattern and is used to evaluate (interpret) the sentence for a
|
|
||||||
* client.
|
|
||||||
* <p>
|
|
||||||
* In this example we use the Interpreter pattern to break sentences into expressions
|
|
||||||
* ({@link Expression}) that can be evaluated and as a whole form the result.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
@ -4,10 +4,7 @@ title: Iterator
|
|||||||
folder: iterator
|
folder: iterator
|
||||||
permalink: /patterns/iterator/
|
permalink: /patterns/iterator/
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Difficulty-Beginner
|
|
||||||
- Gang Of Four
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Provide a way to access the elements of an aggregate object
|
**Intent:** Provide a way to access the elements of an aggregate object
|
||||||
@ -24,7 +21,3 @@ sequentially without exposing its underlying representation.
|
|||||||
**Real world examples:**
|
**Real world examples:**
|
||||||
|
|
||||||
* [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)
|
* [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>iterator</artifactId>
|
<artifactId>iterator</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -2,13 +2,9 @@ package com.iluwatar.iterator;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* The Iterator pattern is a design pattern in which an iterator is used to
|
* Iterator ({@link ItemIterator}) adds abstraction layer on top of a collection
|
||||||
* traverse a container and access the container's elements. The Iterator pattern
|
* ({@link TreasureChest}). This way the collection can change its internal
|
||||||
* decouples algorithms from containers.
|
* implementation without affecting its clients.
|
||||||
* <p>
|
|
||||||
* In this example the Iterator ({@link ItemIterator}) adds abstraction layer on
|
|
||||||
* top of a collection ({@link TreasureChest}). This way the collection can change
|
|
||||||
* its internal implementation without affecting its clients.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
@ -17,8 +17,3 @@ tags: Java
|
|||||||
* you want clearly divide software responsibilities into differents parts of the program
|
* you want clearly divide software responsibilities into differents parts of the program
|
||||||
* you want to prevent a change from propagating throughout the application
|
* you want to prevent a change from propagating throughout the application
|
||||||
* you want to make your application more maintainable and testable
|
* you want to make your application more maintainable and testable
|
||||||
|
|
||||||
**Credits:**
|
|
||||||
|
|
||||||
* [Pattern Oriented Software Architecture Vol I-V](http://www.amazon.com/Pattern-Oriented-Software-Architecture-Volume-Patterns/dp/0471958697)
|
|
||||||
|
|
||||||
|
@ -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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.iluwatar.layers</groupId>
|
<groupId>com.iluwatar.layers</groupId>
|
||||||
<artifactId>layers</artifactId>
|
<artifactId>layers</artifactId>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>lazy-loading</artifactId>
|
<artifactId>lazy-loading</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
package com.iluwatar.lazy.loading;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Using reflection this test shows that the heavy field is not instantiated until the method getHeavy is called
|
|
||||||
*
|
|
||||||
* Created by jones on 11/10/2015.
|
|
||||||
*/
|
|
||||||
public class HolderThreadSafeTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws IllegalAccessException {
|
|
||||||
HolderThreadSafe hts = new HolderThreadSafe();
|
|
||||||
|
|
||||||
{//first call is null
|
|
||||||
Field[] ff = HolderThreadSafe.class.getDeclaredFields();
|
|
||||||
for (Field f: ff) {
|
|
||||||
f.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNull(ff[0].get(hts));
|
|
||||||
}
|
|
||||||
|
|
||||||
// now it is lazily loaded
|
|
||||||
hts.getHeavy();
|
|
||||||
|
|
||||||
{//now it is not null - call via reflection so that the test is the same before and after
|
|
||||||
Field[] ff = HolderThreadSafe.class.getDeclaredFields();
|
|
||||||
for (Field f: ff) {
|
|
||||||
f.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNotNull(ff[0].get(hts));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,10 +4,7 @@ title: Mediator
|
|||||||
folder: mediator
|
folder: mediator
|
||||||
permalink: /patterns/mediator/
|
permalink: /patterns/mediator/
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags: Java
|
||||||
- Java
|
|
||||||
- Gang Of Four
|
|
||||||
- Difficulty-Intermediate
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Intent:** Define an object that encapsulates how a set of objects interact.
|
**Intent:** Define an object that encapsulates how a set of objects interact.
|
||||||
@ -21,7 +18,3 @@ other explicitly, and it lets you vary their interaction independently.
|
|||||||
* a set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand
|
* a set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand
|
||||||
* reusing an object is difficult because it refers to and communicates with many other objects
|
* reusing an object is difficult because it refers to and communicates with many other objects
|
||||||
* a behavior that's distributed between several classes should be customizable without a lot of subclassing
|
* a behavior that's distributed between several classes should be customizable without a lot of subclassing
|
||||||
|
|
||||||
**Credits**
|
|
||||||
|
|
||||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
<project
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<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.6.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>mediator</artifactId>
|
<artifactId>mediator</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user