Compare commits
89 Commits
Author | SHA1 | Date | |
---|---|---|---|
1f27dbbf5b | |||
d20145c05d | |||
464ae1690b | |||
ddbc61b140 | |||
f32a3892a3 | |||
d406f0f9c6 | |||
0c56d800c5 | |||
9074a9ca05 | |||
b14aff17b6 | |||
20c1e2ea80 | |||
100a72a5e2 | |||
a395316a80 | |||
80875a9ac8 | |||
4d820b12ff | |||
e543ee0a9c | |||
2f5a2be27a | |||
e549af25dd | |||
3f7ead5ca5 | |||
aebd857931 | |||
fa077c8be9 | |||
bd1b65276e | |||
448d855809 | |||
f6a20c7693 | |||
e5217bbde8 | |||
40e5c8d587 | |||
c78dd2667a | |||
7aff77ab27 | |||
528d179efe | |||
984bf552ce | |||
414cdfa332 | |||
afb897300b | |||
adb94044ff | |||
35d6a54831 | |||
f135ef6ec8 | |||
046e131119 | |||
e4c34b1e22 | |||
3791a80978 | |||
ab19c47415 | |||
9f086ba72c | |||
cfd83b5753 | |||
81e8d354a9 | |||
c580b61df3 | |||
9714fe075a | |||
bbd769b208 | |||
d3689b2040 | |||
ea81ef71ab | |||
80ff7bb217 | |||
64f1fe8979 | |||
f47b9283c3 | |||
72e08365b8 | |||
3e526cb5da | |||
50310aaeaf | |||
b70614efef | |||
dfef28e93e | |||
0003c6cb00 | |||
6ab9b36d59 | |||
2fa705ab59 | |||
8fabc861b3 | |||
53fdaba6c4 | |||
8b625a8d3c | |||
022ab28e20 | |||
f1122f78e3 | |||
cd077fa490 | |||
823dc6395f | |||
221b71781a | |||
b5d4445d63 | |||
f64ba22c64 | |||
632174b6dc | |||
57be8aa522 | |||
9c5745763d | |||
1655f30845 | |||
769a6206f2 | |||
9b6517453f | |||
df4a40fc13 | |||
83533543e6 | |||
f71e186959 | |||
db2140ecc9 | |||
049841298e | |||
1e5cbe1f76 | |||
53cc97e9d0 | |||
33224dd7d7 | |||
d8378915a1 | |||
0e7fae21c3 | |||
3ef464986c | |||
d3eb8a2ef2 | |||
083065ba93 | |||
cca40a543a | |||
64b89ecb59 | |||
10bbf988ea |
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Ilkka Seppälä
|
||||
Copyright (c) 2014-2016 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>abstract-factory</artifactId>
|
||||
<dependencies>
|
||||
|
@ -52,14 +52,6 @@ public class App {
|
||||
setArmy(factory.createArmy());
|
||||
}
|
||||
|
||||
ElfKingdomFactory getElfKingdomFactory() {
|
||||
return new ElfKingdomFactory();
|
||||
}
|
||||
|
||||
OrcKingdomFactory getOrcKingdomFactory() {
|
||||
return new OrcKingdomFactory();
|
||||
}
|
||||
|
||||
King getKing(final KingdomFactory factory) {
|
||||
return factory.createKing();
|
||||
}
|
||||
@ -107,17 +99,13 @@ public class App {
|
||||
App app = new App();
|
||||
|
||||
System.out.println("Elf Kingdom");
|
||||
KingdomFactory elfKingdomFactory;
|
||||
elfKingdomFactory = app.getElfKingdomFactory();
|
||||
app.createKingdom(elfKingdomFactory);
|
||||
app.createKingdom(new ElfKingdomFactory());
|
||||
System.out.println(app.getArmy().getDescription());
|
||||
System.out.println(app.getCastle().getDescription());
|
||||
System.out.println(app.getKing().getDescription());
|
||||
|
||||
System.out.println("\nOrc Kingdom");
|
||||
KingdomFactory orcKingdomFactory;
|
||||
orcKingdomFactory = app.getOrcKingdomFactory();
|
||||
app.createKingdom(orcKingdomFactory);
|
||||
app.createKingdom(new OrcKingdomFactory());
|
||||
System.out.println(app.getArmy().getDescription());
|
||||
System.out.println(app.getCastle().getDescription());
|
||||
System.out.println(app.getKing().getDescription());
|
||||
|
@ -36,8 +36,8 @@ public class AbstractFactoryTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
elfFactory = app.getElfKingdomFactory();
|
||||
orcFactory = app.getOrcKingdomFactory();
|
||||
elfFactory = new ElfKingdomFactory();
|
||||
orcFactory = new OrcKingdomFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>adapter</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>async-method-invocation</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>bridge</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>builder</artifactId>
|
||||
<dependencies>
|
||||
|
@ -27,7 +27,7 @@ package com.iluwatar.builder;
|
||||
* Hero, the class with many parameters.
|
||||
*
|
||||
*/
|
||||
public class Hero {
|
||||
public final class Hero {
|
||||
|
||||
private final Profession profession;
|
||||
private final String name;
|
||||
@ -36,6 +36,15 @@ public class Hero {
|
||||
private final Armor armor;
|
||||
private final Weapon weapon;
|
||||
|
||||
private Hero(HeroBuilder builder) {
|
||||
this.profession = builder.profession;
|
||||
this.name = builder.name;
|
||||
this.hairColor = builder.hairColor;
|
||||
this.hairType = builder.hairType;
|
||||
this.weapon = builder.weapon;
|
||||
this.armor = builder.armor;
|
||||
}
|
||||
|
||||
public Profession getProfession() {
|
||||
return profession;
|
||||
}
|
||||
@ -88,15 +97,6 @@ public class Hero {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private Hero(HeroBuilder builder) {
|
||||
this.profession = builder.profession;
|
||||
this.name = builder.name;
|
||||
this.hairColor = builder.hairColor;
|
||||
this.hairType = builder.hairType;
|
||||
this.weapon = builder.weapon;
|
||||
this.armor = builder.armor;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The builder class.
|
||||
|
@ -30,7 +30,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>business-delegate</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>caching</artifactId>
|
||||
<dependencies>
|
||||
|
@ -33,7 +33,7 @@ import java.text.ParseException;
|
||||
* CacheStore class.
|
||||
*
|
||||
*/
|
||||
public class AppManager {
|
||||
public final class AppManager {
|
||||
|
||||
private static CachingPolicy cachingPolicy;
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
package com.iluwatar.caching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -31,7 +31,7 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class CacheStore {
|
||||
|
||||
static LruCache cache = null;
|
||||
static LruCache cache;
|
||||
|
||||
private CacheStore() {
|
||||
}
|
||||
@ -134,7 +134,7 @@ public class CacheStore {
|
||||
if (null == cache) {
|
||||
return;
|
||||
}
|
||||
ArrayList<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
|
||||
List<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
|
||||
for (UserAccount userAccount : listOfUserAccounts) {
|
||||
DbManager.upsertDb(userAccount);
|
||||
}
|
||||
@ -144,7 +144,7 @@ public class CacheStore {
|
||||
* Print user accounts
|
||||
*/
|
||||
public static String print() {
|
||||
ArrayList<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
|
||||
List<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("\n--CACHE CONTENT--\n");
|
||||
for (UserAccount userAccount : listOfUserAccounts) {
|
||||
|
@ -24,6 +24,7 @@ package com.iluwatar.caching;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
@ -43,13 +44,13 @@ import com.mongodb.client.model.UpdateOptions;
|
||||
* during runtime (createVirtualDB()).</p>
|
||||
*
|
||||
*/
|
||||
public class DbManager {
|
||||
public final class DbManager {
|
||||
|
||||
private static MongoClient mongoClient;
|
||||
private static MongoDatabase db;
|
||||
private static boolean useMongoDB;
|
||||
|
||||
private static HashMap<String, UserAccount> virtualDB;
|
||||
private static Map<String, UserAccount> virtualDB;
|
||||
|
||||
private DbManager() {
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ package com.iluwatar.caching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -49,9 +51,9 @@ public class LruCache {
|
||||
}
|
||||
|
||||
int capacity;
|
||||
HashMap<String, Node> cache = new HashMap<>();
|
||||
Node head = null;
|
||||
Node end = null;
|
||||
Map<String, Node> cache = new HashMap<>();
|
||||
Node head;
|
||||
Node end;
|
||||
|
||||
public LruCache(int capacity) {
|
||||
this.capacity = capacity;
|
||||
@ -161,7 +163,7 @@ public class LruCache {
|
||||
*
|
||||
* Returns cache data in list form.
|
||||
*/
|
||||
public ArrayList<UserAccount> getCacheDataInListForm() {
|
||||
public List<UserAccount> getCacheDataInListForm() {
|
||||
ArrayList<UserAccount> listOfCacheData = new ArrayList<>();
|
||||
Node temp = head;
|
||||
while (temp != null) {
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>callback</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>chain</artifactId>
|
||||
<dependencies>
|
||||
|
@ -44,7 +44,7 @@ public class Request {
|
||||
* Indicates if the request is handled or not. A request can only switch state from unhandled to
|
||||
* handled, there's no way to 'unhandle' a request
|
||||
*/
|
||||
private boolean handled = false;
|
||||
private boolean handled;
|
||||
|
||||
/**
|
||||
* Create a new request of the given type and accompanied description.
|
||||
|
@ -38,6 +38,7 @@ Use the Command pattern when you want to
|
||||
## Real world examples
|
||||
|
||||
* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
|
||||
* [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)
|
||||
|
||||
## Credits
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>command</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>composite</artifactId>
|
||||
<dependencies>
|
||||
|
BIN
dao/etc/dao.png
BIN
dao/etc/dao.png
Binary file not shown.
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 39 KiB |
@ -1,45 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.8" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
|
||||
associations="true" dependencies="false" nesting-relationships="true">
|
||||
<class id="1" language="java" name="com.iluwatar.Customer" project="dao"
|
||||
file="/dao/src/main/java/com/iluwatar/Customer.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="176" y="337"/>
|
||||
<class id="1" language="java" name="com.iluwatar.dao.App" project="dao"
|
||||
file="/dao/src/main/java/com/iluwatar/dao/App.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="910" y="191"/>
|
||||
<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"/>
|
||||
<attributes public="true" package="true" protected="true" private="false" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="false" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="2" language="java" name="com.iluwatar.CustomerDaoImpl" project="dao"
|
||||
file="/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="540" y="334"/>
|
||||
<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>
|
||||
<interface id="3" language="java" name="com.iluwatar.CustomerDao" project="dao"
|
||||
file="/dao/src/main/java/com/iluwatar/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="536" y="131"/>
|
||||
<interface id="2" language="java" name="com.iluwatar.dao.CustomerDao" project="dao"
|
||||
file="/dao/src/main/java/com/iluwatar/dao/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="536" y="187"/>
|
||||
<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>
|
||||
</interface>
|
||||
<realization id="4">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="3"/>
|
||||
</realization>
|
||||
<association id="5">
|
||||
<end type="SOURCE" refId="2" navigable="false">
|
||||
<attribute id="6" name="customers"/>
|
||||
<multiplicity id="7" minimum="0" maximum="2147483647"/>
|
||||
<class id="3" language="java" name="com.iluwatar.dao.InMemoryCustomerDao" project="dao"
|
||||
file="/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="289" y="455"/>
|
||||
<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="false" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="4" language="java" name="com.iluwatar.dao.DBCustomerDao" project="dao"
|
||||
file="/dao/src/main/java/com/iluwatar/dao/DBCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="751" y="456"/>
|
||||
<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="false" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="false" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="5" language="java" name="javax.sql.DataSource" project="dao"
|
||||
file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="1083" y="459"/>
|
||||
<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>
|
||||
</interface>
|
||||
<association id="6">
|
||||
<end type="SOURCE" refId="4" navigable="false">
|
||||
<attribute id="7" name="dataSource"/>
|
||||
<multiplicity id="8" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<end type="TARGET" refId="5" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="9">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</realization>
|
||||
<dependency id="10">
|
||||
<end type="SOURCE" refId="1"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</dependency>
|
||||
<realization id="11">
|
||||
<end type="SOURCE" refId="4"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</realization>
|
||||
<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"/>
|
||||
|
14
dao/pom.xml
14
dao/pom.xml
@ -30,7 +30,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>dao</artifactId>
|
||||
|
||||
@ -44,6 +44,18 @@
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.bechte.junit</groupId>
|
||||
<artifactId>junit-hierarchicalcontextrunner</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -20,49 +20,101 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.h2.jdbcx.JdbcDataSource;
|
||||
|
||||
/**
|
||||
*
|
||||
* 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 interacting with the data. The below example demonstrates basic CRUD operations: select,
|
||||
* add, update, and delete.
|
||||
*
|
||||
* <p>With the DAO pattern, we can use various method calls to retrieve/add/delete/update data
|
||||
* without directly interacting with the data source. The below example demonstrates basic CRUD
|
||||
* operations: select, add, update, and delete.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
|
||||
private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
|
||||
private static Logger log = Logger.getLogger(App.class);
|
||||
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args command line args.
|
||||
* @throws Exception if any error occurs.
|
||||
*/
|
||||
public static void main(final String[] args) {
|
||||
final CustomerDaoImpl customerDao = new CustomerDaoImpl(generateSampleCustomers());
|
||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
||||
log.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2));
|
||||
public static void main(final String[] args) throws Exception {
|
||||
final CustomerDao inMemoryDao = new InMemoryCustomerDao();
|
||||
performOperationsUsing(inMemoryDao);
|
||||
|
||||
final DataSource dataSource = createDataSource();
|
||||
createSchema(dataSource);
|
||||
final CustomerDao dbDao = new DbCustomerDao(dataSource);
|
||||
performOperationsUsing(dbDao);
|
||||
deleteSchema(dataSource);
|
||||
}
|
||||
|
||||
private static void deleteSchema(DataSource dataSource) throws SQLException {
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
Statement statement = connection.createStatement()) {
|
||||
statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);
|
||||
}
|
||||
}
|
||||
|
||||
private static void createSchema(DataSource dataSource) throws SQLException {
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
Statement statement = connection.createStatement()) {
|
||||
statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
|
||||
}
|
||||
}
|
||||
|
||||
private static DataSource createDataSource() {
|
||||
JdbcDataSource dataSource = new JdbcDataSource();
|
||||
dataSource.setURL(DB_URL);
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {
|
||||
addCustomers(customerDao);
|
||||
log.info("customerDao.getAllCustomers(): ");
|
||||
try (Stream<Customer> customerStream = customerDao.getAll()) {
|
||||
customerStream.forEach((customer) -> log.info(customer));
|
||||
}
|
||||
log.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
|
||||
final Customer customer = new Customer(4, "Dan", "Danson");
|
||||
customerDao.addCustomer(customer);
|
||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
||||
customerDao.add(customer);
|
||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
|
||||
customer.setFirstName("Daniel");
|
||||
customer.setLastName("Danielson");
|
||||
customerDao.updateCustomer(customer);
|
||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
||||
customerDao.deleteCustomer(customer);
|
||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
|
||||
customerDao.update(customer);
|
||||
log.info("customerDao.getAllCustomers(): ");
|
||||
try (Stream<Customer> customerStream = customerDao.getAll()) {
|
||||
customerStream.forEach((cust) -> log.info(cust));
|
||||
}
|
||||
customerDao.delete(customer);
|
||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
|
||||
}
|
||||
|
||||
private static void addCustomers(CustomerDao customerDao) throws Exception {
|
||||
for (Customer customer : generateSampleCustomers()) {
|
||||
customerDao.add(customer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,11 +20,11 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.dao;
|
||||
|
||||
/**
|
||||
*
|
||||
* Customer
|
||||
* A customer POJO that represents the data that will be read from the data source.
|
||||
*
|
||||
*/
|
||||
public class Customer {
|
||||
@ -34,7 +34,7 @@ public class Customer {
|
||||
private String lastName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Creates an instance of customer.
|
||||
*/
|
||||
public Customer(final int id, final String firstName, final String lastName) {
|
||||
this.id = id;
|
||||
@ -73,12 +73,12 @@ public class Customer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
public boolean equals(final Object that) {
|
||||
boolean isEqual = false;
|
||||
if (this == o) {
|
||||
if (this == that) {
|
||||
isEqual = true;
|
||||
} else if (o != null && getClass() == o.getClass()) {
|
||||
final Customer customer = (Customer) o;
|
||||
} else if (that != null && getClass() == that.getClass()) {
|
||||
final Customer customer = (Customer) that;
|
||||
if (getId() == customer.getId()) {
|
||||
isEqual = true;
|
||||
}
|
||||
|
@ -20,24 +20,62 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* In an application the Data Access Object (DAO) is a part of Data access layer. It is an object
|
||||
* that provides an interface to some type of persistence mechanism. By mapping application calls
|
||||
* to the persistence layer, DAO provides 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,
|
||||
* database schema, etc.
|
||||
*
|
||||
* CustomerDao
|
||||
*
|
||||
* <p>Any change in the way data is stored and retrieved will not change the client code as the
|
||||
* client will be using interface and need not worry about exact source.
|
||||
*
|
||||
* @see InMemoryCustomerDao
|
||||
* @see DbCustomerDao
|
||||
*/
|
||||
public interface CustomerDao {
|
||||
|
||||
List<Customer> getAllCustomers();
|
||||
/**
|
||||
* @return all the customers as a stream. The stream may be lazily or eagerly evaluated based
|
||||
* on the implementation. The stream must be closed after use.
|
||||
* @throws Exception if any error occurs.
|
||||
*/
|
||||
Stream<Customer> getAll() throws Exception;
|
||||
|
||||
/**
|
||||
* @param id unique identifier of the customer.
|
||||
* @return an optional with customer if a customer with unique identifier <code>id</code>
|
||||
* exists, empty optional otherwise.
|
||||
* @throws Exception if any error occurs.
|
||||
*/
|
||||
Optional<Customer> getById(int id) throws Exception;
|
||||
|
||||
Customer getCustomerById(int id);
|
||||
/**
|
||||
* @param customer the customer to be added.
|
||||
* @return true if customer is successfully added, false if customer already exists.
|
||||
* @throws Exception if any error occurs.
|
||||
*/
|
||||
boolean add(Customer customer) throws Exception;
|
||||
|
||||
void addCustomer(Customer customer);
|
||||
/**
|
||||
* @param customer the customer to be updated.
|
||||
* @return true if customer exists and is successfully updated, false otherwise.
|
||||
* @throws Exception if any error occurs.
|
||||
*/
|
||||
boolean update(Customer customer) throws Exception;
|
||||
|
||||
void updateCustomer(Customer customer);
|
||||
|
||||
void deleteCustomer(Customer customer);
|
||||
/**
|
||||
* @param customer the customer to be deleted.
|
||||
* @return true if customer exists and is successfully deleted, false otherwise.
|
||||
* @throws Exception if any error occurs.
|
||||
*/
|
||||
boolean delete(Customer customer) throws Exception;
|
||||
}
|
||||
|
@ -1,84 +0,0 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* The 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, database schema, etc.
|
||||
*
|
||||
*/
|
||||
public class CustomerDaoImpl implements CustomerDao {
|
||||
|
||||
// Represents the DB structure for our example so we don't have to managed it ourselves
|
||||
// Note: Normally this would be in the form of an actual database and not part of the Dao Impl.
|
||||
private List<Customer> customers;
|
||||
|
||||
public CustomerDaoImpl(final List<Customer> customers) {
|
||||
this.customers = customers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Customer> getAllCustomers() {
|
||||
return customers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Customer getCustomerById(final int id) {
|
||||
Customer customer = null;
|
||||
for (final Customer cus : getAllCustomers()) {
|
||||
if (cus.getId() == id) {
|
||||
customer = cus;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return customer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCustomer(final Customer customer) {
|
||||
if (getCustomerById(customer.getId()) == null) {
|
||||
customers.add(customer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateCustomer(final Customer customer) {
|
||||
if (getAllCustomers().contains(customer)) {
|
||||
final int index = getAllCustomers().indexOf(customer);
|
||||
getAllCustomers().set(index, customer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCustomer(final Customer customer) {
|
||||
getAllCustomers().remove(customer);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.iluwatar.dao;
|
||||
|
||||
public interface CustomerSchemaSql {
|
||||
|
||||
String CREATE_SCHEMA_SQL = "CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), "
|
||||
+ "LNAME VARCHAR(100))";
|
||||
|
||||
String DELETE_SCHEMA_SQL = "DROP TABLE CUSTOMERS";
|
||||
}
|
183
dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java
Normal file
183
dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java
Normal file
@ -0,0 +1,183 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* An implementation of {@link CustomerDao} that persists customers in RDBMS.
|
||||
*
|
||||
*/
|
||||
public class DbCustomerDao implements CustomerDao {
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
/**
|
||||
* Creates an instance of {@link DbCustomerDao} which uses provided <code>dataSource</code>
|
||||
* to store and retrieve customer information.
|
||||
*
|
||||
* @param dataSource a non-null dataSource.
|
||||
*/
|
||||
public DbCustomerDao(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a lazily populated stream of customers. Note the stream returned must be closed to
|
||||
* free all the acquired resources. The stream keeps an open connection to the database till
|
||||
* it is complete or is closed manually.
|
||||
*/
|
||||
@Override
|
||||
public Stream<Customer> getAll() throws Exception {
|
||||
|
||||
Connection connection;
|
||||
try {
|
||||
connection = getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS");
|
||||
ResultSet resultSet = statement.executeQuery();
|
||||
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE,
|
||||
Spliterator.ORDERED) {
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super Customer> action) {
|
||||
try {
|
||||
if (!resultSet.next()) {
|
||||
return false;
|
||||
}
|
||||
action.accept(createCustomer(resultSet));
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}, false).onClose(() -> mutedClose(connection));
|
||||
} catch (SQLException e) {
|
||||
throw new Exception(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private Connection getConnection() throws SQLException {
|
||||
return dataSource.getConnection();
|
||||
}
|
||||
|
||||
private void mutedClose(Connection connection) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private Customer createCustomer(ResultSet resultSet) throws SQLException {
|
||||
return new Customer(resultSet.getInt("ID"),
|
||||
resultSet.getString("FNAME"),
|
||||
resultSet.getString("LNAME"));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Optional<Customer> getById(int id) throws Exception {
|
||||
try (Connection connection = getConnection();
|
||||
PreparedStatement statement =
|
||||
connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
|
||||
|
||||
statement.setInt(1, id);
|
||||
ResultSet resultSet = statement.executeQuery();
|
||||
if (resultSet.next()) {
|
||||
return Optional.of(createCustomer(resultSet));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
throw new Exception(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean add(Customer customer) throws Exception {
|
||||
if (getById(customer.getId()).isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try (Connection connection = getConnection();
|
||||
PreparedStatement statement =
|
||||
connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) {
|
||||
statement.setInt(1, customer.getId());
|
||||
statement.setString(2, customer.getFirstName());
|
||||
statement.setString(3, customer.getLastName());
|
||||
statement.execute();
|
||||
return true;
|
||||
} catch (SQLException ex) {
|
||||
throw new Exception(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean update(Customer customer) throws Exception {
|
||||
try (Connection connection = getConnection();
|
||||
PreparedStatement statement =
|
||||
connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) {
|
||||
statement.setString(1, customer.getFirstName());
|
||||
statement.setString(2, customer.getLastName());
|
||||
statement.setInt(3, customer.getId());
|
||||
return statement.executeUpdate() > 0;
|
||||
} catch (SQLException ex) {
|
||||
throw new Exception(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean delete(Customer customer) throws Exception {
|
||||
try (Connection connection = getConnection();
|
||||
PreparedStatement statement =
|
||||
connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) {
|
||||
statement.setInt(1, customer.getId());
|
||||
return statement.executeUpdate() > 0;
|
||||
} catch (SQLException ex) {
|
||||
throw new Exception(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
73
dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java
Normal file
73
dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* An in memory implementation of {@link CustomerDao}, which stores the customers in JVM memory
|
||||
* and data is lost when the application exits.
|
||||
* <br/>
|
||||
* This implementation is useful as temporary database or for testing.
|
||||
*/
|
||||
public class InMemoryCustomerDao implements CustomerDao {
|
||||
|
||||
private Map<Integer, Customer> idToCustomer = new HashMap<>();
|
||||
|
||||
/**
|
||||
* An eagerly evaluated stream of customers stored in memory.
|
||||
*/
|
||||
@Override
|
||||
public Stream<Customer> getAll() {
|
||||
return idToCustomer.values().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Customer> getById(final int id) {
|
||||
return Optional.ofNullable(idToCustomer.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(final Customer customer) {
|
||||
if (getById(customer.getId()).isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idToCustomer.put(customer.getId(), customer);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(final Customer customer) {
|
||||
return idToCustomer.replace(customer.getId(), customer) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(final Customer customer) {
|
||||
return idToCustomer.remove(customer.getId()) != null;
|
||||
}
|
||||
}
|
@ -20,18 +20,17 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Tests that DAO example runs without errors.
|
||||
*/
|
||||
public class AppTest {
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
public void test() throws Exception {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
|
@ -1,121 +0,0 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
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", "Krueger");
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
customers = new ArrayList<>();
|
||||
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;
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
247
dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java
Normal file
247
dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java
Normal file
@ -0,0 +1,247 @@
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.h2.jdbcx.JdbcDataSource;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import de.bechte.junit.runners.context.HierarchicalContextRunner;
|
||||
|
||||
/**
|
||||
* Tests {@link DbCustomerDao}.
|
||||
*/
|
||||
@RunWith(HierarchicalContextRunner.class)
|
||||
public class DbCustomerDaoTest {
|
||||
|
||||
private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
|
||||
private DbCustomerDao dao;
|
||||
private Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
|
||||
|
||||
/**
|
||||
* Creates customers schema.
|
||||
* @throws SQLException if there is any error while creating schema.
|
||||
*/
|
||||
@Before
|
||||
public void createSchema() throws SQLException {
|
||||
try (Connection connection = DriverManager.getConnection(DB_URL);
|
||||
Statement statement = connection.createStatement()) {
|
||||
statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the scenario where DB connectivity is present.
|
||||
*/
|
||||
public class ConnectionSuccess {
|
||||
|
||||
/**
|
||||
* Setup for connection success scenario.
|
||||
* @throws Exception if any error occurs.
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
JdbcDataSource dataSource = new JdbcDataSource();
|
||||
dataSource.setURL(DB_URL);
|
||||
dao = new DbCustomerDao(dataSource);
|
||||
boolean result = dao.add(existingCustomer);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the scenario when DAO operations are being performed on a non existing customer.
|
||||
*/
|
||||
public class NonExistingCustomer {
|
||||
|
||||
@Test
|
||||
public void addingShouldResultInSuccess() throws Exception {
|
||||
try (Stream<Customer> allCustomers = dao.getAll()) {
|
||||
assumeTrue(allCustomers.count() == 1);
|
||||
}
|
||||
|
||||
final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
|
||||
boolean result = dao.add(nonExistingCustomer);
|
||||
assertTrue(result);
|
||||
|
||||
assertCustomerCountIs(2);
|
||||
assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
|
||||
final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
|
||||
boolean result = dao.delete(nonExistingCustomer);
|
||||
|
||||
assertFalse(result);
|
||||
assertCustomerCountIs(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
|
||||
final int nonExistingId = getNonExistingCustomerId();
|
||||
final String newFirstname = "Douglas";
|
||||
final String newLastname = "MacArthur";
|
||||
final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
|
||||
boolean result = dao.update(customer);
|
||||
|
||||
assertFalse(result);
|
||||
assertFalse(dao.getById(nonExistingId).isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveShouldReturnNoCustomer() throws Exception {
|
||||
assertFalse(dao.getById(getNonExistingCustomerId()).isPresent());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a scenario where DAO operations are being performed on an already existing
|
||||
* customer.
|
||||
*
|
||||
*/
|
||||
public class ExistingCustomer {
|
||||
|
||||
@Test
|
||||
public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception {
|
||||
Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
|
||||
|
||||
boolean result = dao.add(existingCustomer);
|
||||
|
||||
assertFalse(result);
|
||||
assertCustomerCountIs(1);
|
||||
assertEquals(existingCustomer, dao.getById(existingCustomer.getId()).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception {
|
||||
boolean result = dao.delete(existingCustomer);
|
||||
|
||||
assertTrue(result);
|
||||
assertCustomerCountIs(0);
|
||||
assertFalse(dao.getById(existingCustomer.getId()).isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception {
|
||||
final String newFirstname = "Bernard";
|
||||
final String newLastname = "Montgomery";
|
||||
final Customer customer = new Customer(existingCustomer.getId(), newFirstname, newLastname);
|
||||
boolean result = dao.update(customer);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final Customer cust = dao.getById(existingCustomer.getId()).get();
|
||||
assertEquals(newFirstname, cust.getFirstName());
|
||||
assertEquals(newLastname, cust.getLastName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a scenario where DB connectivity is not present due to network issue, or
|
||||
* DB service unavailable.
|
||||
*
|
||||
*/
|
||||
public class ConnectivityIssue {
|
||||
|
||||
private static final String EXCEPTION_CAUSE = "Connection not available";
|
||||
@Rule public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
/**
|
||||
* setup a connection failure scenario.
|
||||
* @throws SQLException if any error occurs.
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws SQLException {
|
||||
dao = new DbCustomerDao(mockedDatasource());
|
||||
exception.expect(Exception.class);
|
||||
exception.expectMessage(EXCEPTION_CAUSE);
|
||||
}
|
||||
|
||||
private DataSource mockedDatasource() throws SQLException {
|
||||
DataSource mockedDataSource = mock(DataSource.class);
|
||||
Connection mockedConnection = mock(Connection.class);
|
||||
SQLException exception = new SQLException(EXCEPTION_CAUSE);
|
||||
doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString());
|
||||
doReturn(mockedConnection).when(mockedDataSource).getConnection();
|
||||
return mockedDataSource;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addingACustomerFailsWithExceptionAsFeedbackToClient() throws Exception {
|
||||
dao.add(new Customer(2, "Bernard", "Montgomery"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletingACustomerFailsWithExceptionAsFeedbackToTheClient() throws Exception {
|
||||
dao.delete(existingCustomer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatingACustomerFailsWithFeedbackToTheClient() throws Exception {
|
||||
final String newFirstname = "Bernard";
|
||||
final String newLastname = "Montgomery";
|
||||
|
||||
dao.update(new Customer(existingCustomer.getId(), newFirstname, newLastname));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrievingACustomerByIdFailsWithExceptionAsFeedbackToClient() throws Exception {
|
||||
dao.getById(existingCustomer.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrievingAllCustomersFailsWithExceptionAsFeedbackToClient() throws Exception {
|
||||
dao.getAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete customer schema for fresh setup per test.
|
||||
* @throws SQLException if any error occurs.
|
||||
*/
|
||||
@After
|
||||
public void deleteSchema() throws SQLException {
|
||||
try (Connection connection = DriverManager.getConnection(DB_URL);
|
||||
Statement statement = connection.createStatement()) {
|
||||
statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertCustomerCountIs(int count) throws Exception {
|
||||
try (Stream<Customer> allCustomers = dao.getAll()) {
|
||||
assertTrue(allCustomers.count() == count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
164
dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java
Normal file
164
dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java
Normal file
@ -0,0 +1,164 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.dao;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import de.bechte.junit.runners.context.HierarchicalContextRunner;
|
||||
|
||||
/**
|
||||
* Tests {@link InMemoryCustomerDao}.
|
||||
*/
|
||||
@RunWith(HierarchicalContextRunner.class)
|
||||
public class InMemoryCustomerDaoTest {
|
||||
|
||||
private InMemoryCustomerDao dao;
|
||||
private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger");
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
dao = new InMemoryCustomerDao();
|
||||
assertTrue(dao.add(CUSTOMER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the scenario when the DAO operations are being performed on a non existent
|
||||
* customer.
|
||||
*/
|
||||
public class NonExistingCustomer {
|
||||
|
||||
@Test
|
||||
public void addingShouldResultInSuccess() throws Exception {
|
||||
try (Stream<Customer> allCustomers = dao.getAll()) {
|
||||
assumeTrue(allCustomers.count() == 1);
|
||||
}
|
||||
|
||||
final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
|
||||
boolean result = dao.add(nonExistingCustomer);
|
||||
assertTrue(result);
|
||||
|
||||
assertCustomerCountIs(2);
|
||||
assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
|
||||
final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
|
||||
boolean result = dao.delete(nonExistingCustomer);
|
||||
|
||||
assertFalse(result);
|
||||
assertCustomerCountIs(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
|
||||
final int nonExistingId = getNonExistingCustomerId();
|
||||
final String newFirstname = "Douglas";
|
||||
final String newLastname = "MacArthur";
|
||||
final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
|
||||
boolean result = dao.update(customer);
|
||||
|
||||
assertFalse(result);
|
||||
assertFalse(dao.getById(nonExistingId).isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveShouldReturnNoCustomer() throws Exception {
|
||||
assertFalse(dao.getById(getNonExistingCustomerId()).isPresent());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the scenario when the DAO operations are being performed on an already existing
|
||||
* customer.
|
||||
*/
|
||||
public class ExistingCustomer {
|
||||
|
||||
@Test
|
||||
public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception {
|
||||
boolean result = dao.add(CUSTOMER);
|
||||
|
||||
assertFalse(result);
|
||||
assertCustomerCountIs(1);
|
||||
assertEquals(CUSTOMER, dao.getById(CUSTOMER.getId()).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception {
|
||||
boolean result = dao.delete(CUSTOMER);
|
||||
|
||||
assertTrue(result);
|
||||
assertCustomerCountIs(0);
|
||||
assertFalse(dao.getById(CUSTOMER.getId()).isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception {
|
||||
final String newFirstname = "Bernard";
|
||||
final String newLastname = "Montgomery";
|
||||
final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname);
|
||||
boolean result = dao.update(customer);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final Customer cust = dao.getById(CUSTOMER.getId()).get();
|
||||
assertEquals(newFirstname, cust.getFirstName());
|
||||
assertEquals(newLastname, cust.getLastName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retriveShouldReturnTheCustomer() {
|
||||
Optional<Customer> optionalCustomer = dao.getById(CUSTOMER.getId());
|
||||
|
||||
assertTrue(optionalCustomer.isPresent());
|
||||
assertEquals(CUSTOMER, optionalCustomer.get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
private void assertCustomerCountIs(int count) throws Exception {
|
||||
try (Stream<Customer> allCustomers = dao.getAll()) {
|
||||
assertTrue(allCustomers.count() == count);
|
||||
}
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>decorator</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,6 +29,7 @@ package com.iluwatar.decorator;
|
||||
*/
|
||||
public class Troll implements Hostile {
|
||||
|
||||
@Override
|
||||
public void attack() {
|
||||
System.out.println("The troll swings at you with a club!");
|
||||
}
|
||||
@ -38,6 +39,7 @@ public class Troll implements Hostile {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fleeBattle() {
|
||||
System.out.println("The troll shrieks in horror and runs away!");
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>dependency-injection</artifactId>
|
||||
<dependencies>
|
||||
|
@ -27,7 +27,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>double-checked-locking</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>double-dispatch</artifactId>
|
||||
<dependencies>
|
||||
|
@ -28,7 +28,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>event-aggregator</artifactId>
|
||||
<dependencies>
|
||||
|
@ -43,7 +43,7 @@ public abstract class EventEmitter {
|
||||
registerObserver(obs);
|
||||
}
|
||||
|
||||
public void registerObserver(EventObserver obs) {
|
||||
public final void registerObserver(EventObserver obs) {
|
||||
observers.add(obs);
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 57 KiB |
@ -4,7 +4,7 @@
|
||||
<class id="1" language="java" name="com.iluwatar.eda.model.User" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="937" y="618"/>
|
||||
<position height="-1" width="-1" x="437" y="535"/>
|
||||
<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"/>
|
||||
@ -15,7 +15,7 @@
|
||||
project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="936" y="90"/>
|
||||
<position height="-1" width="-1" x="763" y="379"/>
|
||||
<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"/>
|
||||
@ -26,17 +26,17 @@
|
||||
project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="101" width="200" x="41" y="37"/>
|
||||
<position height="-1" width="-1" x="596" y="272"/>
|
||||
<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>
|
||||
<interface id="4" language="java" name="com.iluwatar.eda.framework.Message" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java" binary="false"
|
||||
<interface id="4" language="java" name="com.iluwatar.eda.framework.Event" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Event.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="298" y="189"/>
|
||||
<position height="-1" width="-1" x="188" y="121"/>
|
||||
<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"/>
|
||||
@ -46,7 +46,7 @@
|
||||
<interface id="5" language="java" name="com.iluwatar.eda.framework.Handler" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="532" y="89"/>
|
||||
<position height="-1" width="-1" x="755" y="58"/>
|
||||
<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"/>
|
||||
@ -56,7 +56,7 @@
|
||||
<class id="6" language="java" name="com.iluwatar.eda.framework.EventDispatcher" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="613" y="292"/>
|
||||
<position height="-1" width="-1" x="499" y="122"/>
|
||||
<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"/>
|
||||
@ -66,7 +66,7 @@
|
||||
<class id="7" language="java" name="com.iluwatar.eda.event.UserCreatedEvent" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="145" y="618"/>
|
||||
<position height="-1" width="-1" x="102" y="380"/>
|
||||
<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"/>
|
||||
@ -76,17 +76,17 @@
|
||||
<class id="8" language="java" name="com.iluwatar.eda.event.UserUpdatedEvent" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="769" y="455"/>
|
||||
<position height="-1" width="-1" x="320" y="382"/>
|
||||
<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="9" language="java" name="com.iluwatar.eda.event.Event" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java" binary="false"
|
||||
<class id="9" language="java" name="com.iluwatar.eda.event.AbstractEvent" project="event-driven-architecture"
|
||||
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/event/AbstractEvent.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="299" y="460"/>
|
||||
<position height="-1" width="-1" x="188" y="240"/>
|
||||
<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"/>
|
||||
@ -94,99 +94,87 @@
|
||||
</display>
|
||||
</class>
|
||||
<dependency id="10">
|
||||
<bendpoint x="869" y="253"/>
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</dependency>
|
||||
<dependency id="11">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</dependency>
|
||||
<dependency id="12">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="8"/>
|
||||
</dependency>
|
||||
<dependency id="11">
|
||||
<bendpoint x="140" y="196"/>
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</dependency>
|
||||
<dependency id="12">
|
||||
<bendpoint x="17" y="90"/>
|
||||
<bendpoint x="17" y="708"/>
|
||||
<bendpoint x="939" y="703"/>
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</dependency>
|
||||
<dependency id="13">
|
||||
<bendpoint x="935" y="318"/>
|
||||
<bendpoint x="936" y="417"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</dependency>
|
||||
<dependency id="14">
|
||||
<bendpoint x="757" y="378"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</dependency>
|
||||
<generalization id="15">
|
||||
<end type="SOURCE" refId="7"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</generalization>
|
||||
<association id="16">
|
||||
<end type="SOURCE" refId="8" navigable="false">
|
||||
<attribute id="17" name="user"/>
|
||||
<multiplicity id="18" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="19">
|
||||
<realization id="13">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="5"/>
|
||||
</realization>
|
||||
<dependency id="20">
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</dependency>
|
||||
<dependency id="21">
|
||||
<bendpoint x="301" y="114"/>
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</dependency>
|
||||
<realization id="22">
|
||||
<end type="SOURCE" refId="9"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</realization>
|
||||
<dependency id="23">
|
||||
<end type="SOURCE" refId="6"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</dependency>
|
||||
<generalization id="24">
|
||||
<end type="SOURCE" refId="8"/>
|
||||
<generalization id="14">
|
||||
<end type="SOURCE" refId="7"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</generalization>
|
||||
<dependency id="25">
|
||||
<bendpoint x="141" y="250"/>
|
||||
<realization id="15">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="7"/>
|
||||
</dependency>
|
||||
<association id="26">
|
||||
<end type="TARGET" refId="5"/>
|
||||
</realization>
|
||||
<association id="16">
|
||||
<end type="SOURCE" refId="6" navigable="false">
|
||||
<attribute id="27" name="handlers">
|
||||
<position height="19" width="56" x="449" y="175"/>
|
||||
<attribute id="17" name="handlers">
|
||||
<position height="19" width="56" x="672" y="144"/>
|
||||
</attribute>
|
||||
<multiplicity id="28" minimum="0" maximum="2147483647">
|
||||
<position height="17" width="23" x="574" y="173"/>
|
||||
<multiplicity id="18" minimum="0" maximum="2147483647">
|
||||
<position height="17" width="23" x="797" y="142"/>
|
||||
</multiplicity>
|
||||
</end>
|
||||
<end type="TARGET" refId="5" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="29">
|
||||
<end type="SOURCE" refId="7" navigable="false">
|
||||
<attribute id="30" name="user"/>
|
||||
<multiplicity id="31" minimum="0" maximum="1"/>
|
||||
<realization id="19">
|
||||
<end type="SOURCE" refId="9"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</realization>
|
||||
<dependency id="20">
|
||||
<end type="SOURCE" refId="6"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</dependency>
|
||||
<dependency id="21">
|
||||
<bendpoint x="187" y="57"/>
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</dependency>
|
||||
<association id="22">
|
||||
<end type="SOURCE" refId="8" navigable="false">
|
||||
<attribute id="23" name="user">
|
||||
<position height="0" width="0" x="-500" y="-83"/>
|
||||
</attribute>
|
||||
<multiplicity id="24" minimum="0" maximum="1">
|
||||
<position height="0" width="0" x="-500" y="-83"/>
|
||||
</multiplicity>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<realization id="32">
|
||||
<generalization id="25">
|
||||
<end type="SOURCE" refId="8"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</generalization>
|
||||
<association id="26">
|
||||
<end type="SOURCE" refId="7" navigable="false">
|
||||
<attribute id="27" name="user">
|
||||
<position height="0" width="0" x="-500" y="-83"/>
|
||||
</attribute>
|
||||
<multiplicity id="28" minimum="0" maximum="1">
|
||||
<position height="0" width="0" x="-500" y="-83"/>
|
||||
</multiplicity>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<dependency id="29">
|
||||
<bendpoint x="308" y="303"/>
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="5"/>
|
||||
</realization>
|
||||
<end type="TARGET" refId="7"/>
|
||||
</dependency>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="true" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
|
@ -31,7 +31,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>event-driven-architecture</artifactId>
|
||||
|
@ -22,9 +22,9 @@
|
||||
*/
|
||||
package com.iluwatar.eda;
|
||||
|
||||
import com.iluwatar.eda.event.Event;
|
||||
import com.iluwatar.eda.event.UserCreatedEvent;
|
||||
import com.iluwatar.eda.event.UserUpdatedEvent;
|
||||
import com.iluwatar.eda.framework.Event;
|
||||
import com.iluwatar.eda.framework.EventDispatcher;
|
||||
import com.iluwatar.eda.handler.UserCreatedEventHandler;
|
||||
import com.iluwatar.eda.handler.UserUpdatedEventHandler;
|
||||
@ -53,12 +53,12 @@ public class App {
|
||||
public static void main(String[] args) {
|
||||
|
||||
EventDispatcher dispatcher = new EventDispatcher();
|
||||
dispatcher.registerChannel(UserCreatedEvent.class, new UserCreatedEventHandler());
|
||||
dispatcher.registerChannel(UserUpdatedEvent.class, new UserUpdatedEventHandler());
|
||||
dispatcher.registerHandler(UserCreatedEvent.class, new UserCreatedEventHandler());
|
||||
dispatcher.registerHandler(UserUpdatedEvent.class, new UserUpdatedEventHandler());
|
||||
|
||||
User user = new User("iluwatar");
|
||||
dispatcher.onEvent(new UserCreatedEvent(user));
|
||||
dispatcher.onEvent(new UserUpdatedEvent(user));
|
||||
dispatcher.dispatch(new UserCreatedEvent(user));
|
||||
dispatcher.dispatch(new UserUpdatedEvent(user));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,10 +23,10 @@
|
||||
package com.iluwatar.eda.event;
|
||||
|
||||
import com.iluwatar.eda.framework.EventDispatcher;
|
||||
import com.iluwatar.eda.framework.Message;
|
||||
import com.iluwatar.eda.framework.Event;
|
||||
|
||||
/**
|
||||
* The {@link Event} class serves as a base class for defining custom events happening with your
|
||||
* The {@link AbstractEvent} class serves as a base class for defining custom events happening with your
|
||||
* system. In this example we have two types of events defined.
|
||||
* <ul>
|
||||
* <li>{@link UserCreatedEvent} - used when a user is created</li>
|
||||
@ -34,16 +34,16 @@ import com.iluwatar.eda.framework.Message;
|
||||
* </ul>
|
||||
* Events can be distinguished using the {@link #getType() getType} method.
|
||||
*/
|
||||
public class Event implements Message {
|
||||
public abstract class AbstractEvent implements Event {
|
||||
|
||||
/**
|
||||
* Returns the event type as a {@link Class} object
|
||||
* In this example, this method is used by the {@link EventDispatcher} to
|
||||
* dispatch events depending on their type.
|
||||
*
|
||||
* @return the Event type as a {@link Class}.
|
||||
* @return the AbstractEvent type as a {@link Class}.
|
||||
*/
|
||||
public Class<? extends Message> getType() {
|
||||
public Class<? extends Event> getType() {
|
||||
return getClass();
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ import com.iluwatar.eda.model.User;
|
||||
* This class can be extended to contain details about the user has been created. In this example,
|
||||
* the entire {@link User} object is passed on as data with the event.
|
||||
*/
|
||||
public class UserCreatedEvent extends Event {
|
||||
public class UserCreatedEvent extends AbstractEvent {
|
||||
|
||||
private User user;
|
||||
|
||||
|
@ -29,7 +29,7 @@ import com.iluwatar.eda.model.User;
|
||||
* This class can be extended to contain details about the user has been updated. In this example,
|
||||
* the entire {@link User} object is passed on as data with the event.
|
||||
*/
|
||||
public class UserUpdatedEvent extends Event {
|
||||
public class UserUpdatedEvent extends AbstractEvent {
|
||||
|
||||
private User user;
|
||||
|
||||
|
@ -23,15 +23,15 @@
|
||||
package com.iluwatar.eda.framework;
|
||||
|
||||
/**
|
||||
* A {@link Message} is an object with a specific type that is associated
|
||||
* A {@link Event} is an object with a specific type that is associated
|
||||
* to a specific {@link Handler}.
|
||||
*/
|
||||
public interface Message {
|
||||
public interface Event {
|
||||
|
||||
/**
|
||||
* Returns the message type as a {@link Class} object. In this example the message type is
|
||||
* used to handle events by their type.
|
||||
* @return the message type as a {@link Class}.
|
||||
*/
|
||||
Class<? extends Message> getType();
|
||||
Class<? extends Event> getType();
|
||||
}
|
@ -22,19 +22,16 @@
|
||||
*/
|
||||
package com.iluwatar.eda.framework;
|
||||
|
||||
import com.iluwatar.eda.event.Event;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handles the routing of {@link Event} messages to associated handlers.
|
||||
* A {@link HashMap} is used to store the association between events and their respective handlers.
|
||||
*
|
||||
*/
|
||||
public class EventDispatcher {
|
||||
|
||||
private Map<Class<? extends Event>, Handler<?>> handlers;
|
||||
private Map<Class<? extends Event>, Handler<? extends Event>> handlers;
|
||||
|
||||
public EventDispatcher() {
|
||||
handlers = new HashMap<>();
|
||||
@ -46,8 +43,8 @@ public class EventDispatcher {
|
||||
* @param eventType The {@link Event} to be registered
|
||||
* @param handler The {@link Handler} that will be handling the {@link Event}
|
||||
*/
|
||||
public void registerChannel(Class<? extends Event> eventType,
|
||||
Handler<?> handler) {
|
||||
public <E extends Event> void registerHandler(Class<E> eventType,
|
||||
Handler<E> handler) {
|
||||
handlers.put(eventType, handler);
|
||||
}
|
||||
|
||||
@ -56,8 +53,12 @@ public class EventDispatcher {
|
||||
*
|
||||
* @param event The {@link Event} to be dispatched
|
||||
*/
|
||||
public void onEvent(Event event) {
|
||||
handlers.get(event.getClass()).onEvent(event);
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E extends Event> void dispatch(E event) {
|
||||
Handler<E> handler = (Handler<E>) handlers.get(event.getClass());
|
||||
if (handler != null) {
|
||||
handler.onEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -22,13 +22,11 @@
|
||||
*/
|
||||
package com.iluwatar.eda.framework;
|
||||
|
||||
import com.iluwatar.eda.event.Event;
|
||||
|
||||
/**
|
||||
* This interface can be implemented to handle different types of messages.
|
||||
* Every handler is responsible for a single of type message
|
||||
*/
|
||||
public interface Handler<E extends Message> {
|
||||
public interface Handler<E extends Event> {
|
||||
|
||||
/**
|
||||
* The onEvent method should implement and handle behavior related to the event.
|
||||
@ -36,5 +34,5 @@ public interface Handler<E extends Message> {
|
||||
* a queue to be consumed by other sub systems.
|
||||
* @param event the {@link Event} object to be handled.
|
||||
*/
|
||||
void onEvent(Event event);
|
||||
void onEvent(E event);
|
||||
}
|
@ -22,7 +22,6 @@
|
||||
*/
|
||||
package com.iluwatar.eda.handler;
|
||||
|
||||
import com.iluwatar.eda.event.Event;
|
||||
import com.iluwatar.eda.event.UserCreatedEvent;
|
||||
import com.iluwatar.eda.framework.Handler;
|
||||
|
||||
@ -32,9 +31,10 @@ import com.iluwatar.eda.framework.Handler;
|
||||
public class UserCreatedEventHandler implements Handler<UserCreatedEvent> {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event message) {
|
||||
public void onEvent(UserCreatedEvent event) {
|
||||
|
||||
UserCreatedEvent userCreatedEvent = (UserCreatedEvent) message;
|
||||
System.out.printf("User with %s has been Created!", userCreatedEvent.getUser().getUsername());
|
||||
System.out.println(String.format(
|
||||
"User '%s' has been Created!", event.getUser().getUsername()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
*/
|
||||
package com.iluwatar.eda.handler;
|
||||
|
||||
import com.iluwatar.eda.event.Event;
|
||||
import com.iluwatar.eda.event.UserUpdatedEvent;
|
||||
import com.iluwatar.eda.framework.Handler;
|
||||
|
||||
@ -32,9 +31,9 @@ import com.iluwatar.eda.framework.Handler;
|
||||
public class UserUpdatedEventHandler implements Handler<UserUpdatedEvent> {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event message) {
|
||||
public void onEvent(UserUpdatedEvent event) {
|
||||
|
||||
UserUpdatedEvent userUpdatedEvent = (UserUpdatedEvent) message;
|
||||
System.out.printf("User with %s has been Updated!", userUpdatedEvent.getUser().getUsername());
|
||||
System.out.println(String.format(
|
||||
"User '%s' has been Updated!", event.getUser().getUsername()));
|
||||
}
|
||||
}
|
||||
|
@ -29,13 +29,13 @@ import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* {@link UserCreatedEventTest} tests and verifies {@link Event} behaviour.
|
||||
* {@link UserCreatedEventTest} tests and verifies {@link AbstractEvent} behaviour.
|
||||
*/
|
||||
public class UserCreatedEventTest {
|
||||
|
||||
/**
|
||||
* This unit test should correctly return the {@link Event} class type when calling the
|
||||
* {@link Event#getType() getType} method.
|
||||
* This unit test should correctly return the {@link AbstractEvent} class type when calling the
|
||||
* {@link AbstractEvent#getType() getType} method.
|
||||
*/
|
||||
@Test
|
||||
public void testGetEventType() {
|
||||
|
@ -22,7 +22,6 @@
|
||||
*/
|
||||
package com.iluwatar.eda.framework;
|
||||
|
||||
import com.iluwatar.eda.framework.EventDispatcher;
|
||||
import com.iluwatar.eda.event.UserCreatedEvent;
|
||||
import com.iluwatar.eda.event.UserUpdatedEvent;
|
||||
import com.iluwatar.eda.handler.UserCreatedEventHandler;
|
||||
@ -49,8 +48,8 @@ public class EventDispatcherTest {
|
||||
EventDispatcher dispatcher = spy(new EventDispatcher());
|
||||
UserCreatedEventHandler userCreatedEventHandler = spy(new UserCreatedEventHandler());
|
||||
UserUpdatedEventHandler userUpdatedEventHandler = spy(new UserUpdatedEventHandler());
|
||||
dispatcher.registerChannel(UserCreatedEvent.class, userCreatedEventHandler);
|
||||
dispatcher.registerChannel(UserUpdatedEvent.class, userUpdatedEventHandler);
|
||||
dispatcher.registerHandler(UserCreatedEvent.class, userCreatedEventHandler);
|
||||
dispatcher.registerHandler(UserUpdatedEvent.class, userUpdatedEventHandler);
|
||||
|
||||
User user = new User("iluwatar");
|
||||
|
||||
@ -58,15 +57,14 @@ public class EventDispatcherTest {
|
||||
UserUpdatedEvent userUpdatedEvent = new UserUpdatedEvent(user);
|
||||
|
||||
//fire a userCreatedEvent and verify that userCreatedEventHandler has been invoked.
|
||||
dispatcher.onEvent(userCreatedEvent);
|
||||
dispatcher.dispatch(userCreatedEvent);
|
||||
verify(userCreatedEventHandler).onEvent(userCreatedEvent);
|
||||
verify(dispatcher).onEvent(userCreatedEvent);
|
||||
verify(dispatcher).dispatch(userCreatedEvent);
|
||||
|
||||
//fire a userCreatedEvent and verify that userUpdatedEventHandler has been invoked.
|
||||
dispatcher.onEvent(userUpdatedEvent);
|
||||
dispatcher.dispatch(userUpdatedEvent);
|
||||
verify(userUpdatedEventHandler).onEvent(userUpdatedEvent);
|
||||
verify(dispatcher).onEvent(userUpdatedEvent);
|
||||
verify(dispatcher).dispatch(userUpdatedEvent);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>execute-around</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>facade</artifactId>
|
||||
<dependencies>
|
||||
|
@ -60,7 +60,7 @@ public class DwarvenGoldmineFacade {
|
||||
makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);
|
||||
}
|
||||
|
||||
private void makeActions(Collection<DwarvenMineWorker> workers,
|
||||
private static void makeActions(Collection<DwarvenMineWorker> workers,
|
||||
DwarvenMineWorker.Action... actions) {
|
||||
for (DwarvenMineWorker worker : workers) {
|
||||
worker.action(actions);
|
||||
|
28
factory-kit/README.md
Normal file
28
factory-kit/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
layout: pattern
|
||||
title: Factory Kit
|
||||
folder: factory-kit
|
||||
permalink: /patterns/factory-kit/
|
||||
categories: Creational
|
||||
tags:
|
||||
- Java
|
||||
- Difficulty-Beginner
|
||||
- Functional
|
||||
---
|
||||
|
||||
## Intent
|
||||
Define a factory of immutable content with separated builder and factory interfaces.
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
Use the Factory Kit pattern when
|
||||
|
||||
* a class can't anticipate the class of objects it must create
|
||||
* you just want a new instance of a custom builder instead of the global one
|
||||
* you explicitly want to define types of objects, that factory can build
|
||||
* you want a separated builder and creator interface
|
||||
|
||||
## Credits
|
||||
|
||||
* [Design Pattern Reloaded by Remi Forax: ](https://www.youtube.com/watch?v=-k2X7guaArU)
|
BIN
factory-kit/etc/factory-kit.png
Normal file
BIN
factory-kit/etc/factory-kit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
10
factory-kit/etc/factory-kit.ucls
Normal file
10
factory-kit/etc/factory-kit.ucls
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.9" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||
<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>
|
48
factory-kit/pom.xml
Normal file
48
factory-kit/pom.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
|
||||
The MIT License
|
||||
Copyright (c) 2014 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<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.11.0</version>
|
||||
</parent>
|
||||
<artifactId>factory-kit</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
54
factory-kit/src/main/java/com/iluwatar/factorykit/App.java
Normal file
54
factory-kit/src/main/java/com/iluwatar/factorykit/App.java
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
/**
|
||||
* Factory-kit is a creational pattern which defines a factory of immutable content
|
||||
* with separated builder and factory interfaces to deal with the problem of
|
||||
* creating one of the objects specified directly in the factory-kit instance.
|
||||
*
|
||||
* <p>
|
||||
* In the given example {@link WeaponFactory} represents the factory-kit, that contains
|
||||
* four {@link Builder}s for creating new objects of
|
||||
* the classes implementing {@link Weapon} interface.
|
||||
* <br>Each of them can be called with {@link WeaponFactory#create(WeaponType)} method, with
|
||||
* an input representing an instance of {@link WeaponType} that needs to
|
||||
* be mapped explicitly with desired class type in the factory instance.
|
||||
*/
|
||||
public class App {
|
||||
/**
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
WeaponFactory factory = WeaponFactory.factory(builder -> {
|
||||
builder.add(WeaponType.SWORD, Sword::new);
|
||||
builder.add(WeaponType.AXE, Axe::new);
|
||||
builder.add(WeaponType.SPEAR, Spear::new);
|
||||
builder.add(WeaponType.BOW, Bow::new);
|
||||
});
|
||||
Weapon axe = factory.create(WeaponType.AXE);
|
||||
System.out.println(axe);
|
||||
}
|
||||
}
|
30
factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java
Normal file
30
factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
public class Axe implements Weapon {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Axe";
|
||||
}
|
||||
}
|
30
factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java
Normal file
30
factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
public class Bow implements Weapon {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Bow";
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Functional interface that allows adding builder with name to the factory.
|
||||
*/
|
||||
public interface Builder {
|
||||
void add(WeaponType name, Supplier<Weapon> supplier);
|
||||
}
|
30
factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java
Normal file
30
factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
public class Spear implements Weapon {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Spear";
|
||||
}
|
||||
}
|
30
factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java
Normal file
30
factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
public class Sword implements Weapon {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Sword";
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
/**
|
||||
* Interface representing weapon.
|
||||
*/
|
||||
public interface Weapon {
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Functional interface, an example of the factory-kit design pattern.
|
||||
* <br>Instance created locally gives an opportunity to strictly define
|
||||
* which objects types the instance of a factory will be able to create.
|
||||
* <br>Factory is a placeholder for {@link Builder}s
|
||||
* with {@link WeaponFactory#create(WeaponType)} method to initialize new objects.
|
||||
*/
|
||||
public interface WeaponFactory {
|
||||
|
||||
/**
|
||||
* Creates an instance of the given type.
|
||||
* @param name representing enum of an object type to be created.
|
||||
* @return new instance of a requested class implementing {@link Weapon} interface.
|
||||
*/
|
||||
Weapon create(WeaponType name);
|
||||
|
||||
/**
|
||||
* Creates factory - placeholder for specified {@link Builder}s.
|
||||
* @param consumer for the new builder to the factory.
|
||||
* @return factory with specified {@link Builder}s
|
||||
*/
|
||||
static WeaponFactory factory(Consumer<Builder> consumer) {
|
||||
HashMap<WeaponType, Supplier<Weapon>> map = new HashMap<>();
|
||||
consumer.accept(map::put);
|
||||
return name -> map.get(name).get();
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit;
|
||||
|
||||
/**
|
||||
* Enumerates {@link Weapon} types
|
||||
*/
|
||||
public enum WeaponType {
|
||||
SWORD, AXE, BOW, SPEAR
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit.app;
|
||||
|
||||
import com.iluwatar.factorykit.App;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* The MIT License
|
||||
* Copyright (c) 2014 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.factorykit.factorykit;
|
||||
|
||||
import com.iluwatar.factorykit.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class FactoryKitTest {
|
||||
|
||||
private WeaponFactory factory;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
factory = WeaponFactory.factory(builder -> {
|
||||
builder.add(WeaponType.SPEAR, Spear::new);
|
||||
builder.add(WeaponType.AXE, Axe::new);
|
||||
builder.add(WeaponType.SWORD, Sword::new);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing {@link WeaponFactory} to produce a SPEAR asserting that the Weapon is an instance of {@link Spear}
|
||||
*/
|
||||
@Test
|
||||
public void testSpearWeapon() {
|
||||
Weapon weapon = factory.create(WeaponType.SPEAR);
|
||||
verifyWeapon(weapon, Spear.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing {@link WeaponFactory} to produce a AXE asserting that the Weapon is an instance of {@link Axe}
|
||||
*/
|
||||
@Test
|
||||
public void testAxeWeapon() {
|
||||
Weapon weapon = factory.create(WeaponType.AXE);
|
||||
verifyWeapon(weapon, Axe.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Testing {@link WeaponFactory} to produce a SWORD asserting that the Weapon is an instance of {@link Sword}
|
||||
*/
|
||||
@Test
|
||||
public void testWeapon() {
|
||||
Weapon weapon = factory.create(WeaponType.SWORD);
|
||||
verifyWeapon(weapon, Sword.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method asserts that the weapon object that is passed is an instance of the clazz
|
||||
*
|
||||
* @param weapon weapon object which is to be verified
|
||||
* @param clazz expected class of the weapon
|
||||
*/
|
||||
private void verifyWeapon(Weapon weapon, Class clazz) {
|
||||
assertTrue("Weapon must be an object of: " + clazz.getName(), clazz.isInstance(weapon));
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<artifactId>factory-method</artifactId>
|
||||
<dependencies>
|
||||
|
@ -38,25 +38,40 @@ package com.iluwatar.factory.method;
|
||||
*/
|
||||
public class App {
|
||||
|
||||
private final Blacksmith blacksmith;
|
||||
|
||||
/**
|
||||
* Creates an instance of <code>App</code> which will use <code>blacksmith</code> to manufacture
|
||||
* the weapons for war.
|
||||
* <code>App</code> is unaware which concrete implementation of {@link Blacksmith} it is using.
|
||||
* The decision of which blacksmith implementation to use may depend on configuration, or
|
||||
* the type of rival in war.
|
||||
* @param blacksmith a non-null implementation of blacksmith
|
||||
*/
|
||||
public App(Blacksmith blacksmith) {
|
||||
this.blacksmith = blacksmith;
|
||||
}
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Blacksmith blacksmith;
|
||||
// Lets go to war with Orc weapons
|
||||
App app = new App(new OrcBlacksmith());
|
||||
app.manufactureWeapons();
|
||||
|
||||
// Lets go to war with Elf weapons
|
||||
app = new App(new ElfBlacksmith());
|
||||
app.manufactureWeapons();
|
||||
}
|
||||
|
||||
private void manufactureWeapons() {
|
||||
Weapon weapon;
|
||||
|
||||
blacksmith = new OrcBlacksmith();
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
System.out.println(weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
|
||||
System.out.println(weapon);
|
||||
|
||||
blacksmith = new ElfBlacksmith();
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SHORT_SWORD);
|
||||
System.out.println(weapon);
|
||||
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
|
||||
System.out.println(weapon);
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ public class FactoryMethodTest {
|
||||
* @param expectedWeaponType expected WeaponType of the weapon
|
||||
* @param clazz expected class of the weapon
|
||||
*/
|
||||
private void verifyWeapon(Weapon weapon, WeaponType expectedWeaponType, Class clazz) {
|
||||
private void verifyWeapon(Weapon weapon, WeaponType expectedWeaponType, Class<?> clazz) {
|
||||
assertTrue("Weapon must be an object of: " + clazz.getName(), clazz.isInstance(weapon));
|
||||
assertEquals("Weapon must be of weaponType: " + clazz.getName(), expectedWeaponType,
|
||||
weapon.getWeaponType());
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user