Merge branch 'master' of https://github.com/iluwatar/java-design-patterns
This commit is contained in:
15
PULL_REQUEST_TEMPLATE.md
Normal file
15
PULL_REQUEST_TEMPLATE.md
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
Pull request title
|
||||
|
||||
- Clearly and concisely describes what it does
|
||||
- Refer to the issue that it solves, if available
|
||||
|
||||
|
||||
Pull request description
|
||||
|
||||
- Describes the main changes that come with the pull request
|
||||
- Any relevant additional information is provided
|
||||
|
||||
|
||||
|
||||
> For detailed contributing instructions see https://github.com/iluwatar/java-design-patterns/wiki/01.-How-to-contribute
|
@ -8,6 +8,7 @@
|
||||
[](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)
|
||||
[](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://sonarqube.com/dashboard/index/com.iluwatar%3Ajava-design-patterns)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/1503)
|
||||
|
||||
# Introduction
|
||||
|
||||
|
@ -1,67 +0,0 @@
|
||||
#
|
||||
# The MIT License
|
||||
# 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
|
||||
# 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.
|
||||
#
|
||||
|
||||
import requests, glob, re, os
|
||||
|
||||
# taken from here: http://stackoverflow.com/a/13641746
|
||||
def replace(file, pattern, subst):
|
||||
# Read contents from file as a single string
|
||||
file_handle = open(file, 'r')
|
||||
file_string = file_handle.read()
|
||||
file_handle.close()
|
||||
|
||||
# Use RE package to allow for replacement (also allowing for (multiline) REGEX)
|
||||
file_string = (re.sub(pattern, subst, file_string))
|
||||
|
||||
# Write contents to file.
|
||||
# Using mode 'w' truncates the file.
|
||||
file_handle = open(file, 'w')
|
||||
file_handle.write(file_string)
|
||||
file_handle.close()
|
||||
|
||||
# list of all puml files
|
||||
fileList = glob.glob('*/etc/*.puml')
|
||||
for puml in fileList:
|
||||
pathSplit = puml.split("/")
|
||||
# parent folder
|
||||
parent = pathSplit[0]
|
||||
# individual artifact/project name
|
||||
artifact = pathSplit[2].replace(".urm.puml", "")
|
||||
print "parent: " + parent + "; artifact: " + artifact
|
||||
|
||||
# do a POST to the official plantuml hosting site with a little trick "!includeurl" and raw github content
|
||||
data = {
|
||||
'text': "!includeurl https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/" + puml
|
||||
}
|
||||
r = requests.post('http://plantuml.com/plantuml/uml', data=data)
|
||||
pumlId = r.url.replace("http://plantuml.com/plantuml/uml/", "")
|
||||
|
||||
# the only thing needed to get a png/svg/ascii from the server back
|
||||
print "Puml Server ID: " + pumlId
|
||||
|
||||
# add the id so jekyll/liquid can use it
|
||||
if (parent == artifact):
|
||||
replace("./" + parent + "/README.md", "categories:", "pumlid: {}\\ncategories:".format(pumlId))
|
||||
else:
|
||||
print "I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file '" + puml + "'\npumlid: {}".format(pumlId)
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Abstract Document
|
||||
folder: abstract-document
|
||||
permalink: /patterns/abstract-document/
|
||||
pumlid: PSjB3eCm34NHhPG599vtDyQn85L-ifzX-p3lxEf8Twj3MXGDQvyJMFubChxpKN767gucSq07iinEjSNDOACVNvoAUZr6MWoe3QVE_WRnxZ0Mf38b-hkIGlurX_MyehS7
|
||||
categories: Structural
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,59 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.abstractdocument.domain {
|
||||
class Car {
|
||||
+ Car(properties : Map<String, Object>)
|
||||
}
|
||||
interface HasModel {
|
||||
+ PROPERTY : String {static}
|
||||
+ getModel() : Optional<String>
|
||||
}
|
||||
interface HasParts {
|
||||
+ PROPERTY : String {static}
|
||||
+ getParts() : Stream<Part>
|
||||
}
|
||||
interface HasPrice {
|
||||
+ PROPERTY : String {static}
|
||||
+ getPrice() : Optional<Number>
|
||||
}
|
||||
interface HasType {
|
||||
+ PROPERTY : String {static}
|
||||
+ getType() : Optional<String>
|
||||
}
|
||||
class Part {
|
||||
+ Part(properties : Map<String, Object>)
|
||||
}
|
||||
}
|
||||
package com.iluwatar.abstractdocument {
|
||||
abstract class AbstractDocument {
|
||||
- properties : Map<String, Object>
|
||||
# AbstractDocument(properties : Map<String, Object>)
|
||||
+ children(key : String, constructor : Function<Map<String, Object>, T>) : Stream<T>
|
||||
+ get(key : String) : Object
|
||||
+ put(key : String, value : Object)
|
||||
+ toString() : String
|
||||
}
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
interface Document {
|
||||
+ children(String, Function<Map<String, Object>, T>) : Stream<T> {abstract}
|
||||
+ get(String) : Object {abstract}
|
||||
+ put(String, Object) {abstract}
|
||||
}
|
||||
}
|
||||
AbstractDocument ..|> Document
|
||||
Car ..|> HasModel
|
||||
Car ..|> HasPrice
|
||||
Car ..|> HasParts
|
||||
Car --|> AbstractDocument
|
||||
HasModel --|> Document
|
||||
HasParts --|> Document
|
||||
HasPrice --|> Document
|
||||
HasType --|> Document
|
||||
Part ..|> HasType
|
||||
Part ..|> HasModel
|
||||
Part ..|> HasPrice
|
||||
Part --|> AbstractDocument
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>abstract-document</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Abstract Factory
|
||||
folder: abstract-factory
|
||||
permalink: /patterns/abstract-factory/
|
||||
pumlid: PSZB3OD034NHLa81Czwd6sCC39gVxEUWT1_ssLmTtQLqgR5fM7sTmFGtaV6TZu8prd0r6HtQaMKqAZLk1XjT_E6qgPUZfyc0MdTgx0-8LuUn8ErFXdr98NypXxKyezKV
|
||||
categories: Creational
|
||||
tags:
|
||||
- Java
|
||||
@ -120,6 +119,45 @@ king.getDescription(); // Output: This is the Elven king!
|
||||
army.getDescription(); // Output: This is the Elven Army!
|
||||
```
|
||||
|
||||
Now, we can design a factory for our different kingdom factories. In this example, we created FactoryMaker, responsible for returning an instance of either ElfKingdomFactory or OrcKingdomFactory.
|
||||
The client can use FactoryMaker to create the desired concrete factory which, in turn, will produce different concrete objects (Army, King, Castle).
|
||||
In this example, we also used an enum to parameterize which type of kingdom factory the client will ask for.
|
||||
|
||||
```
|
||||
public static class FactoryMaker {
|
||||
|
||||
public enum KingdomType {
|
||||
ELF, ORC
|
||||
}
|
||||
|
||||
public static KingdomFactory makeFactory(KingdomType type) {
|
||||
switch (type) {
|
||||
case ELF:
|
||||
return new ElfKingdomFactory();
|
||||
case ORC:
|
||||
return new OrcKingdomFactory();
|
||||
default:
|
||||
throw new IllegalArgumentException("KingdomType not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
App app = new App();
|
||||
|
||||
LOGGER.info("Elf Kingdom");
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||
LOGGER.info(app.getArmy().getDescription());
|
||||
LOGGER.info(app.getCastle().getDescription());
|
||||
LOGGER.info(app.getKing().getDescription());
|
||||
|
||||
LOGGER.info("Orc Kingdom");
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||
-- similar use of the orc factory
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Applicability
|
||||
Use the Abstract Factory pattern when
|
||||
|
||||
@ -141,6 +179,10 @@ Use the Abstract Factory pattern when
|
||||
|
||||
* Dependency injection in java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time.
|
||||
|
||||
## Presentations
|
||||
|
||||
* [Abstract Factory Pattern](etc/presentation.html)
|
||||
|
||||
## Real world examples
|
||||
|
||||
* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)
|
||||
|
BIN
abstract-factory/etc/diagram1.png
Normal file
BIN
abstract-factory/etc/diagram1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
BIN
abstract-factory/etc/diagram2.png
Normal file
BIN
abstract-factory/etc/diagram2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
190
abstract-factory/etc/presentation.html
Normal file
190
abstract-factory/etc/presentation.html
Normal file
@ -0,0 +1,190 @@
|
||||
<!--
|
||||
|
||||
The MIT License
|
||||
Copyright (c) 2017 Rodolfo Forte
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Design Patterns - Abstract Factory Presentation</title>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
|
||||
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
|
||||
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
|
||||
|
||||
body { font-family: 'Droid Serif'; }
|
||||
h1, h2, h3 {
|
||||
font-family: 'Yanone Kaffeesatz';
|
||||
font-weight: normal;
|
||||
}
|
||||
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
|
||||
|
||||
blockquote {
|
||||
border-left: 0.3em solid rgba(0,0,0,0.5);
|
||||
padding: 0 15px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width:100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<textarea id="source">
|
||||
|
||||
class: center, middle
|
||||
|
||||
# Abstract Factory
|
||||
|
||||
---
|
||||
|
||||
# Also known as
|
||||
|
||||
* Kit
|
||||
|
||||
---
|
||||
|
||||
# Intent
|
||||
|
||||
* Provide an interface for creating families of related or dependent objects without specifying their concrete classes
|
||||
|
||||
---
|
||||
|
||||
# Explanation
|
||||
|
||||
* [Wikipedia](https://en.wikipedia.org/wiki/Abstract_factory_pattern) says:
|
||||
> "The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes"
|
||||
|
||||
<br />
|
||||
|
||||
* In plain words:
|
||||
* A factory that groups individual but related/dependent factories together without specifying their concrete classes;
|
||||
* A factory of factories;
|
||||
|
||||
---
|
||||
|
||||
# Example
|
||||
|
||||
* In a factory that creates kingdoms, we need objects with common theme:
|
||||
|
||||
* Elven kingdom needs an Elven king, Elven castle and Elven army;
|
||||
|
||||
* Orcish kingdom needs an Orcish king, Orcish castle and Orcish army;
|
||||
|
||||
<br />
|
||||
|
||||
* There is a dependency between the objects in the kingdom;
|
||||
|
||||
---
|
||||
|
||||
# Diagram
|
||||
|
||||
* Based on the kingdom example, the diagram below showcases the different concrete factories and their concrete products:
|
||||
|
||||
.center[]
|
||||
|
||||
|
||||
---
|
||||
|
||||
# Diagram
|
||||
|
||||
* The class diagram below showcases the factory of factories;
|
||||
|
||||
* At runtime, we can define which Kingdom type is needed and pass it as a parameter to define which concrete KingdomFactory to instantiate;
|
||||
|
||||
* The concrete factory returned will then be able to produce the related objects of the specified type;
|
||||
|
||||
.center[]
|
||||
|
||||
---
|
||||
|
||||
# Applicability
|
||||
|
||||
Use the Abstract Factory pattern when:
|
||||
|
||||
* A system should be independent of how its products are created, composed and represented;
|
||||
|
||||
* A system should be configured with one of multiple families of products;
|
||||
|
||||
* A family of related product objects is designed to be used together, and you need to enforce this constraint;
|
||||
|
||||
* You want to provide a class library of products, and you want to reveal just their interfaces, not their implementations;
|
||||
|
||||
---
|
||||
|
||||
# Applicability
|
||||
|
||||
Use the Abstract Factory pattern when:
|
||||
|
||||
* The lifetime of the dependency is conceptually shorter than the lifetime of the consumer;
|
||||
|
||||
* You need a run-time value to construct a particular dependency;
|
||||
|
||||
* You want to decide which product to call from a family at runtime;
|
||||
|
||||
* You need to supply one or more parameters only known at run-time before you can resolve a dependency;
|
||||
|
||||
---
|
||||
|
||||
#Use Cases
|
||||
|
||||
* Selecting to call the appropriate implementation of FileSystemAcmeService or DatabaseAcmeService or NetworkAcmeService at runtime;
|
||||
* Unit test case writing becomes much easier;
|
||||
|
||||
---
|
||||
|
||||
# Consequences
|
||||
|
||||
* Dependency injection in java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time
|
||||
|
||||
---
|
||||
|
||||
# Real world examples
|
||||
|
||||
[javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)
|
||||
|
||||
[javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)
|
||||
|
||||
[javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)
|
||||
|
||||
---
|
||||
|
||||
# Credits
|
||||
|
||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
||||
|
||||
---
|
||||
|
||||
# Tutorials
|
||||
|
||||
* Source code http://java-design-patterns.com/patterns/abstract-factory/
|
||||
|
||||
</textarea>
|
||||
<script src="https://gnab.github.io/remark/downloads/remark-latest.min.js">
|
||||
</script>
|
||||
<script>
|
||||
var slideshow = remark.create();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>abstract-factory</artifactId>
|
||||
<dependencies>
|
||||
|
@ -25,6 +25,8 @@ package com.iluwatar.abstractfactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.iluwatar.abstractfactory.App.FactoryMaker.KingdomType;
|
||||
|
||||
/**
|
||||
*
|
||||
* The Abstract Factory pattern provides a way to encapsulate a group of individual factories that have a common theme
|
||||
@ -94,7 +96,34 @@ public class App {
|
||||
}
|
||||
|
||||
/**
|
||||
* Program entry point
|
||||
* The factory of kingdom factories.
|
||||
*/
|
||||
public static class FactoryMaker {
|
||||
|
||||
/**
|
||||
* Enumeration for the different types of Kingdoms.
|
||||
*/
|
||||
public enum KingdomType {
|
||||
ELF, ORC
|
||||
}
|
||||
|
||||
/**
|
||||
* The factory method to create KingdomFactory concrete objects.
|
||||
*/
|
||||
public static KingdomFactory makeFactory(KingdomType type) {
|
||||
switch (type) {
|
||||
case ELF:
|
||||
return new ElfKingdomFactory();
|
||||
case ORC:
|
||||
return new OrcKingdomFactory();
|
||||
default:
|
||||
throw new IllegalArgumentException("KingdomType not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args
|
||||
* command line args
|
||||
@ -104,17 +133,15 @@ public class App {
|
||||
App app = new App();
|
||||
|
||||
LOGGER.info("Elf Kingdom");
|
||||
app.createKingdom(new ElfKingdomFactory());
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||
LOGGER.info(app.getArmy().getDescription());
|
||||
LOGGER.info(app.getCastle().getDescription());
|
||||
LOGGER.info(app.getKing().getDescription());
|
||||
|
||||
LOGGER.info("Orc Kingdom");
|
||||
app.createKingdom(new OrcKingdomFactory());
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||
LOGGER.info(app.getArmy().getDescription());
|
||||
LOGGER.info(app.getCastle().getDescription());
|
||||
LOGGER.info(app.getKing().getDescription());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -25,6 +25,9 @@ package com.iluwatar.abstractfactory;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.iluwatar.abstractfactory.App.FactoryMaker;
|
||||
import com.iluwatar.abstractfactory.App.FactoryMaker.KingdomType;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -39,8 +42,8 @@ public class AbstractFactoryTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
elfFactory = new ElfKingdomFactory();
|
||||
orcFactory = new OrcKingdomFactory();
|
||||
elfFactory = FactoryMaker.makeFactory(KingdomType.ELF);
|
||||
orcFactory = FactoryMaker.makeFactory(KingdomType.ORC);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Adapter
|
||||
folder: adapter
|
||||
permalink: /patterns/adapter/
|
||||
pumlid: DSR14S8m30J0Lg20M7-wEMnDOiPMFDA9j0yyUEtUkzMHJTF7xI1NF4GSLzaxZtncgDVJgCPIpobzv0N2vOKtjgRHTziMI7KBcOXl10thfxB-Nz9dMJd71m00
|
||||
categories: Structural
|
||||
tags:
|
||||
- Java
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>adapter</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Aggregator Microservices
|
||||
folder: aggregator-microservices
|
||||
permalink: /patterns/aggregator-microservices/
|
||||
pumlid: JOov3SCm301NIGQGs7iRXYPa1g8ayB7NjuiKwGvtmBrbKC-Tq_hhY5Y-0HXUjKaS-Kbdepc2HrIQ2jBpma23BvvOTdPfeooCO1iEYlu0O6l63MDQKI6Rp-CKOWSE-ey_NzEqhjH-0m00
|
||||
categories: Architectural
|
||||
tags:
|
||||
- Java
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>aggregator-microservices</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -1,43 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.aggregator.microservices {
|
||||
class Aggregator {
|
||||
- informationClient : ProductInformationClient
|
||||
- inventoryClient : ProductInventoryClient
|
||||
+ Aggregator()
|
||||
+ getProduct() : Product
|
||||
}
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class Product {
|
||||
- productInventories : int
|
||||
- title : String
|
||||
+ Product()
|
||||
+ getProductInventories() : int
|
||||
+ getTitle() : String
|
||||
+ setProductInventories(productInventories : int)
|
||||
+ setTitle(title : String)
|
||||
}
|
||||
interface ProductInformationClient {
|
||||
+ getProductTitle() : String {abstract}
|
||||
}
|
||||
class ProductInformationClientImpl {
|
||||
- LOGGER : Logger {static}
|
||||
+ ProductInformationClientImpl()
|
||||
+ getProductTitle() : String
|
||||
}
|
||||
interface ProductInventoryClient {
|
||||
+ getProductInventories() : int {abstract}
|
||||
}
|
||||
class ProductInventoryClientImpl {
|
||||
- LOGGER : Logger {static}
|
||||
+ ProductInventoryClientImpl()
|
||||
+ getProductInventories() : int
|
||||
}
|
||||
}
|
||||
Aggregator --> "-informationClient" ProductInformationClient
|
||||
Aggregator --> "-inventoryClient" ProductInventoryClient
|
||||
ProductInformationClientImpl ..|> ProductInformationClient
|
||||
ProductInventoryClientImpl ..|> ProductInventoryClient
|
||||
@enduml
|
@ -1,12 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.information.microservice {
|
||||
class InformationApplication {
|
||||
+ InformationApplication()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class InformationController {
|
||||
+ InformationController()
|
||||
+ getProductTitle() : String
|
||||
}
|
||||
}
|
||||
@enduml
|
@ -1,12 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.inventory.microservice {
|
||||
class InventoryApplication {
|
||||
+ InventoryApplication()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class InventoryController {
|
||||
+ InventoryController()
|
||||
+ getProductInventories() : int
|
||||
}
|
||||
}
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>aggregator-microservices</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>aggregator-microservices</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -29,32 +29,11 @@
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>aggregator-microservices</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.github.markusmo3.urm</groupId>
|
||||
<artifactId>urm-maven-plugin</artifactId>
|
||||
<version>${urm.version}</version>
|
||||
<configuration combine.self="override">
|
||||
<outputDirectory>${project.basedir}/../etc</outputDirectory>
|
||||
<packages>
|
||||
<param>com.iluwatar</param>
|
||||
</packages>
|
||||
<skipForProjects>
|
||||
<!-- skip for parent project -->
|
||||
<param>aggregator-microservices</param>
|
||||
</skipForProjects>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<modules>
|
||||
<module>information-microservice</module>
|
||||
<module>aggregator-service</module>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: API Gateway
|
||||
folder: api-gateway
|
||||
permalink: /patterns/api-gateway/
|
||||
pumlid: JSox3SCm303HLP819FRUXg49cO542_nOyFPncUvUSszHwhbpMdyT4TCt0CDLcyIHdtGsEZLOez8vG7ek33JuueLbPvUcPM84cpeCz2S0fvI6mGjluA1_b-Tt2N5D6tNcw3y0
|
||||
categories: Architectural
|
||||
tags:
|
||||
- Java
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>api-gateway</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>api-gateway-service</artifactId>
|
||||
|
@ -1,48 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.api.gateway {
|
||||
class ApiGateway {
|
||||
- imageClient : ImageClient
|
||||
- priceClient : PriceClient
|
||||
+ ApiGateway()
|
||||
+ getProductDesktop() : DesktopProduct
|
||||
+ getProductMobile() : MobileProduct
|
||||
}
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class DesktopProduct {
|
||||
- imagePath : String
|
||||
- price : String
|
||||
+ DesktopProduct()
|
||||
+ getImagePath() : String
|
||||
+ getPrice() : String
|
||||
+ setImagePath(imagePath : String)
|
||||
+ setPrice(price : String)
|
||||
}
|
||||
interface ImageClient {
|
||||
+ getImagePath() : String {abstract}
|
||||
}
|
||||
class ImageClientImpl {
|
||||
+ ImageClientImpl()
|
||||
+ getImagePath() : String
|
||||
}
|
||||
class MobileProduct {
|
||||
- price : String
|
||||
+ MobileProduct()
|
||||
+ getPrice() : String
|
||||
+ setPrice(price : String)
|
||||
}
|
||||
interface PriceClient {
|
||||
+ getPrice() : String {abstract}
|
||||
}
|
||||
class PriceClientImpl {
|
||||
+ PriceClientImpl()
|
||||
+ getPrice() : String
|
||||
}
|
||||
}
|
||||
ApiGateway --> "-imageClient" ImageClient
|
||||
ApiGateway --> "-priceClient" PriceClient
|
||||
ImageClientImpl ..|> ImageClient
|
||||
PriceClientImpl ..|> PriceClient
|
||||
@enduml
|
@ -1,12 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.image.microservice {
|
||||
class ImageApplication {
|
||||
+ ImageApplication()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class ImageController {
|
||||
+ ImageController()
|
||||
+ getImagePath() : String
|
||||
}
|
||||
}
|
||||
@enduml
|
@ -1,12 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.price.microservice {
|
||||
class PriceApplication {
|
||||
+ PriceApplication()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class PriceController {
|
||||
+ PriceController()
|
||||
+ getPrice() : String
|
||||
}
|
||||
}
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>api-gateway</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -29,32 +29,11 @@
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>api-gateway</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.github.markusmo3.urm</groupId>
|
||||
<artifactId>urm-maven-plugin</artifactId>
|
||||
<version>${urm.version}</version>
|
||||
<configuration combine.self="override">
|
||||
<outputDirectory>${project.basedir}/../etc</outputDirectory>
|
||||
<packages>
|
||||
<param>com.iluwatar</param>
|
||||
</packages>
|
||||
<skipForProjects>
|
||||
<!-- skip for parent project -->
|
||||
<param>api-gateway</param>
|
||||
</skipForProjects>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<modules>
|
||||
<module>image-microservice</module>
|
||||
<module>price-microservice</module>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>api-gateway</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Async Method Invocation
|
||||
folder: async-method-invocation
|
||||
permalink: /patterns/async-method-invocation/
|
||||
pumlid: TSdB3SCW303GLTe1mFTkunWhk0A3_4dKxTi5UdlIUuhIoCPfuz4Zjhy03EzwIlGyqjbeQR16fJL1HjuOQF362qjZbrFBnWWsTPZeFm3wHwbCZhvQ4RqMOSXIuA1_LzDctJd75m00
|
||||
categories: Concurrency
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,51 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.async.method.invocation {
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ App()
|
||||
- callback(name : String) : AsyncCallback<T> {static}
|
||||
- lazyval(value : T, delayMillis : long) : Callable<T> {static}
|
||||
- log(msg : String) {static}
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
interface AsyncCallback<T> {
|
||||
+ onComplete(T, Optional<Exception>) {abstract}
|
||||
}
|
||||
interface AsyncExecutor {
|
||||
+ endProcess(AsyncResult<T>) : T {abstract}
|
||||
+ startProcess(Callable<T>) : AsyncResult<T> {abstract}
|
||||
+ startProcess(Callable<T>, AsyncCallback<T>) : AsyncResult<T> {abstract}
|
||||
}
|
||||
interface AsyncResult<T> {
|
||||
+ await() {abstract}
|
||||
+ getValue() : T {abstract}
|
||||
+ isCompleted() : boolean {abstract}
|
||||
}
|
||||
class ThreadAsyncExecutor {
|
||||
- idx : AtomicInteger
|
||||
+ ThreadAsyncExecutor()
|
||||
+ endProcess(asyncResult : AsyncResult<T>) : T
|
||||
+ startProcess(task : Callable<T>) : AsyncResult<T>
|
||||
+ startProcess(task : Callable<T>, callback : AsyncCallback<T>) : AsyncResult<T>
|
||||
}
|
||||
-class CompletableResult<T> {
|
||||
~ COMPLETED : int {static}
|
||||
~ FAILED : int {static}
|
||||
~ RUNNING : int {static}
|
||||
~ callback : Optional<AsyncCallback<T>>
|
||||
~ exception : Exception
|
||||
~ lock : Object
|
||||
~ state : int
|
||||
~ value : T
|
||||
~ CompletableResult<T>(callback : AsyncCallback<T>)
|
||||
+ await()
|
||||
+ getValue() : T
|
||||
+ isCompleted() : boolean
|
||||
~ setException(exception : Exception)
|
||||
~ setValue(value : T)
|
||||
}
|
||||
}
|
||||
CompletableResult ..+ ThreadAsyncExecutor
|
||||
ThreadAsyncExecutor ..|> AsyncExecutor
|
||||
CompletableResult ..|> AsyncResult
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>async-method-invocation</artifactId>
|
||||
<dependencies>
|
||||
|
@ -1,24 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.balking {
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class WashingMachine {
|
||||
- LOGGER : Logger {static}
|
||||
- washingMachineState : WashingMachineState
|
||||
+ WashingMachine()
|
||||
+ endOfWashing()
|
||||
+ getWashingMachineState() : WashingMachineState
|
||||
+ wash()
|
||||
}
|
||||
enum WashingMachineState {
|
||||
+ ENABLED {static}
|
||||
+ WASHING {static}
|
||||
+ valueOf(name : String) : WashingMachineState {static}
|
||||
+ values() : WashingMachineState[] {static}
|
||||
}
|
||||
}
|
||||
WashingMachine --> "-washingMachineState" WashingMachineState
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Bridge
|
||||
folder: bridge
|
||||
permalink: /patterns/bridge/
|
||||
pumlid: BSR14SCm20J0Lf82BFxf1akCJ4R26ZZYzkE7zxLljJgoIVfu7S2A3v7pLRhYo3r3l9u6CPHwJjAH5uETllpZhKbejsqn86v1a-CExQwj2mdgqv8-oyev_W00
|
||||
categories: Structural
|
||||
tags:
|
||||
- Java
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>bridge</artifactId>
|
||||
<dependencies>
|
||||
|
@ -44,15 +44,15 @@ public abstract class WeaponTest {
|
||||
assertNotNull(weapon.getEnchantment());
|
||||
|
||||
weapon.swing();
|
||||
verify(enchantment, times(1)).apply();
|
||||
verify(enchantment).apply();
|
||||
verifyNoMoreInteractions(enchantment);
|
||||
|
||||
weapon.wield();
|
||||
verify(enchantment, times(1)).onActivate();
|
||||
verify(enchantment).onActivate();
|
||||
verifyNoMoreInteractions(enchantment);
|
||||
|
||||
weapon.unwield();
|
||||
verify(enchantment, times(1)).onDeactivate();
|
||||
verify(enchantment).onDeactivate();
|
||||
verifyNoMoreInteractions(enchantment);
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Builder
|
||||
folder: builder
|
||||
permalink: /patterns/builder/
|
||||
pumlid: DSR94O0m2030LhG0mzzkC64KXs26GzlNZw_TcRLADagJwOWOlW8OFcNdE79B9wkN1ccKUdLWoGS33KwySMdalEioC89C7Jhw5zYIfNrIrFybhPUHNLu0
|
||||
categories: Creational
|
||||
tags:
|
||||
- Java
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>builder</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Business Delegate
|
||||
folder: business-delegate
|
||||
permalink: /patterns/business-delegate/
|
||||
pumlid: POl13SCm3CHMQGU8zUysgYCuBcJ5a4x9-l6_Fu84tzsgvYxf-Zg06HyYvxkqZYE_6UBrD8YXr7DGrxmPxFJZYxTTeZVR9WFY5ZGu5j2wkad4wYgD8IIe_xQaZp9pw0C0
|
||||
categories: Business Tier
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,57 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.business.delegate {
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class BusinessDelegate {
|
||||
- businessService : BusinessService
|
||||
- lookupService : BusinessLookup
|
||||
- serviceType : ServiceType
|
||||
+ BusinessDelegate()
|
||||
+ doTask()
|
||||
+ setLookupService(businessLookup : BusinessLookup)
|
||||
+ setServiceType(serviceType : ServiceType)
|
||||
}
|
||||
class BusinessLookup {
|
||||
- ejbService : EjbService
|
||||
- jmsService : JmsService
|
||||
+ BusinessLookup()
|
||||
+ getBusinessService(serviceType : ServiceType) : BusinessService
|
||||
+ setEjbService(ejbService : EjbService)
|
||||
+ setJmsService(jmsService : JmsService)
|
||||
}
|
||||
interface BusinessService {
|
||||
+ doProcessing() {abstract}
|
||||
}
|
||||
class Client {
|
||||
- businessDelegate : BusinessDelegate
|
||||
+ Client(businessDelegate : BusinessDelegate)
|
||||
+ doTask()
|
||||
}
|
||||
class EjbService {
|
||||
- LOGGER : Logger {static}
|
||||
+ EjbService()
|
||||
+ doProcessing()
|
||||
}
|
||||
class JmsService {
|
||||
- LOGGER : Logger {static}
|
||||
+ JmsService()
|
||||
+ doProcessing()
|
||||
}
|
||||
enum ServiceType {
|
||||
+ EJB {static}
|
||||
+ JMS {static}
|
||||
+ valueOf(name : String) : ServiceType {static}
|
||||
+ values() : ServiceType[] {static}
|
||||
}
|
||||
}
|
||||
BusinessLookup --> "-ejbService" EjbService
|
||||
BusinessDelegate --> "-serviceType" ServiceType
|
||||
Client --> "-businessDelegate" BusinessDelegate
|
||||
BusinessDelegate --> "-businessService" BusinessService
|
||||
BusinessDelegate --> "-lookupService" BusinessLookup
|
||||
BusinessLookup --> "-jmsService" JmsService
|
||||
EjbService ..|> BusinessService
|
||||
JmsService ..|> BusinessService
|
||||
@enduml
|
@ -30,7 +30,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>business-delegate</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Caching
|
||||
folder: caching
|
||||
permalink: /patterns/caching/
|
||||
pumlid: DSRB4OKm2030LhG0m_rrWyWaE0bc-6ZxpujxsbMKUXwSrfSMCVq7OFYKAj5oJsUZIuCr2bq3fEU3WGOdthWTx59rcnZ1fWu3_GqGKXEjm47VIzeeCqV_0m00
|
||||
categories: Other
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,110 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.caching {
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
+ useCacheAsideStategy()
|
||||
+ useReadAndWriteThroughStrategy()
|
||||
+ useReadThroughAndWriteAroundStrategy()
|
||||
+ useReadThroughAndWriteBehindStrategy()
|
||||
}
|
||||
class AppManager {
|
||||
- cachingPolicy : CachingPolicy {static}
|
||||
- AppManager()
|
||||
+ find(userId : String) : UserAccount {static}
|
||||
- findAside(userId : String) : UserAccount {static}
|
||||
+ initCacheCapacity(capacity : int) {static}
|
||||
+ initCachingPolicy(policy : CachingPolicy) {static}
|
||||
+ initDb(useMongoDb : boolean) {static}
|
||||
+ printCacheContent() : String {static}
|
||||
+ save(userAccount : UserAccount) {static}
|
||||
- saveAside(userAccount : UserAccount) {static}
|
||||
}
|
||||
class CacheStore {
|
||||
- LOGGER : Logger {static}
|
||||
~ cache : LruCache {static}
|
||||
- CacheStore()
|
||||
+ clearCache() {static}
|
||||
+ flushCache() {static}
|
||||
+ get(userId : String) : UserAccount {static}
|
||||
+ initCapacity(capacity : int) {static}
|
||||
+ invalidate(userId : String) {static}
|
||||
+ print() : String {static}
|
||||
+ readThrough(userId : String) : UserAccount {static}
|
||||
+ readThroughWithWriteBackPolicy(userId : String) : UserAccount {static}
|
||||
+ set(userId : String, userAccount : UserAccount) {static}
|
||||
+ writeAround(userAccount : UserAccount) {static}
|
||||
+ writeBehind(userAccount : UserAccount) {static}
|
||||
+ writeThrough(userAccount : UserAccount) {static}
|
||||
}
|
||||
enum CachingPolicy {
|
||||
+ AROUND {static}
|
||||
+ ASIDE {static}
|
||||
+ BEHIND {static}
|
||||
+ THROUGH {static}
|
||||
- policy : String
|
||||
+ getPolicy() : String
|
||||
+ valueOf(name : String) : CachingPolicy {static}
|
||||
+ values() : CachingPolicy[] {static}
|
||||
}
|
||||
class DbManager {
|
||||
- db : MongoDatabase {static}
|
||||
- mongoClient : MongoClient {static}
|
||||
- useMongoDB : boolean {static}
|
||||
- virtualDB : Map<String, UserAccount> {static}
|
||||
- DbManager()
|
||||
+ connect() {static}
|
||||
+ createVirtualDb() {static}
|
||||
+ readFromDb(userId : String) : UserAccount {static}
|
||||
+ updateDb(userAccount : UserAccount) {static}
|
||||
+ upsertDb(userAccount : UserAccount) {static}
|
||||
+ writeToDb(userAccount : UserAccount) {static}
|
||||
}
|
||||
class LruCache {
|
||||
- LOGGER : Logger {static}
|
||||
~ cache : Map<String, Node>
|
||||
~ capacity : int
|
||||
~ end : Node
|
||||
~ head : Node
|
||||
+ LruCache(capacity : int)
|
||||
+ clear()
|
||||
+ contains(userId : String) : boolean
|
||||
+ get(userId : String) : UserAccount
|
||||
+ getCacheDataInListForm() : List<UserAccount>
|
||||
+ getLruData() : UserAccount
|
||||
+ invalidate(userId : String)
|
||||
+ isFull() : boolean
|
||||
+ remove(node : Node)
|
||||
+ set(userId : String, userAccount : UserAccount)
|
||||
+ setCapacity(newCapacity : int)
|
||||
+ setHead(node : Node)
|
||||
}
|
||||
~class Node {
|
||||
~ next : Node
|
||||
~ previous : Node
|
||||
~ userAccount : UserAccount
|
||||
~ userId : String
|
||||
+ Node(this$0 : String, userId : UserAccount)
|
||||
}
|
||||
class UserAccount {
|
||||
- additionalInfo : String
|
||||
- userId : String
|
||||
- userName : String
|
||||
+ UserAccount(userId : String, userName : String, additionalInfo : String)
|
||||
+ getAdditionalInfo() : String
|
||||
+ getUserId() : String
|
||||
+ getUserName() : String
|
||||
+ setAdditionalInfo(additionalInfo : String)
|
||||
+ setUserId(userId : String)
|
||||
+ setUserName(userName : String)
|
||||
+ toString() : String
|
||||
}
|
||||
}
|
||||
LruCache --> "-head" Node
|
||||
Node --+ LruCache
|
||||
Node --> "-previous" Node
|
||||
AppManager --> "-cachingPolicy" CachingPolicy
|
||||
Node --> "-userAccount" UserAccount
|
||||
CacheStore --> "-cache" LruCache
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>caching</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Callback
|
||||
folder: callback
|
||||
permalink: /patterns/callback/
|
||||
pumlid: FSVB4S8m30N0Lg20M7UwUL4qYOciUFGXxSE9s-wp6sjjKgwF8tF6YyXnjxtdKMk5E5-MOjdu6jIrRYIStlXWsIJwRij4fhW53SGFn51TmIT9yZ-jVBHPGxy0
|
||||
categories: Other
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,28 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.callback {
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
interface Callback {
|
||||
+ call() {abstract}
|
||||
}
|
||||
class LambdasApp {
|
||||
- LOGGER : Logger {static}
|
||||
+ LambdasApp()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class SimpleTask {
|
||||
- LOGGER : Logger {static}
|
||||
+ SimpleTask()
|
||||
+ execute()
|
||||
}
|
||||
abstract class Task {
|
||||
+ Task()
|
||||
+ execute() {abstract}
|
||||
+ executeWith(callback : Callback)
|
||||
}
|
||||
}
|
||||
SimpleTask --|> Task
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>callback</artifactId>
|
||||
<dependencies>
|
||||
|
127
chain/README.md
127
chain/README.md
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Chain of responsibility
|
||||
folder: chain
|
||||
permalink: /patterns/chain/
|
||||
pumlid: 9SR13SCm20NGLTe1OkxTXX0KKzd4Wa-pVYlrdTxJN4OTMZ4U7LZv8Wg-ssdejLTgoELGHvDhaesw6HpqvWzlXwQTlYq6D3nfSlv2qjcS5F9VgvXjrHnV
|
||||
categories: Behavioral
|
||||
tags:
|
||||
- Java
|
||||
@ -16,7 +15,131 @@ Avoid coupling the sender of a request to its receiver by giving
|
||||
more than one object a chance to handle the request. Chain the receiving
|
||||
objects and pass the request along the chain until an object handles it.
|
||||
|
||||

|
||||
## Explanation
|
||||
|
||||
Real world example
|
||||
|
||||
> The Orc King gives loud orders to his army. The closest one to react is the commander, then officer and then soldier. The commander, officer and soldier here form a chain of responsibility.
|
||||
|
||||
In plain words
|
||||
|
||||
> It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Translating our example with orcs from above. First we have the request class
|
||||
|
||||
```
|
||||
public class Request {
|
||||
|
||||
private final RequestType requestType;
|
||||
private final String requestDescription;
|
||||
private boolean handled;
|
||||
|
||||
public Request(final RequestType requestType, final String requestDescription) {
|
||||
this.requestType = Objects.requireNonNull(requestType);
|
||||
this.requestDescription = Objects.requireNonNull(requestDescription);
|
||||
}
|
||||
|
||||
public String getRequestDescription() { return requestDescription; }
|
||||
|
||||
public RequestType getRequestType() { return requestType; }
|
||||
|
||||
public void markHandled() { this.handled = true; }
|
||||
|
||||
public boolean isHandled() { return this.handled; }
|
||||
|
||||
@Override
|
||||
public String toString() { return getRequestDescription(); }
|
||||
}
|
||||
|
||||
public enum RequestType {
|
||||
DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX
|
||||
}
|
||||
```
|
||||
|
||||
Then the request handler hierarchy
|
||||
|
||||
```
|
||||
public abstract class RequestHandler {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class);
|
||||
private RequestHandler next;
|
||||
|
||||
public RequestHandler(RequestHandler next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public void handleRequest(Request req) {
|
||||
if (next != null) {
|
||||
next.handleRequest(req);
|
||||
}
|
||||
}
|
||||
|
||||
protected void printHandling(Request req) {
|
||||
LOGGER.info("{} handling request \"{}\"", this, req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract String toString();
|
||||
}
|
||||
|
||||
public class OrcCommander extends RequestHandler {
|
||||
public OrcCommander(RequestHandler handler) {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(Request req) {
|
||||
if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) {
|
||||
printHandling(req);
|
||||
req.markHandled();
|
||||
} else {
|
||||
super.handleRequest(req);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Orc commander";
|
||||
}
|
||||
}
|
||||
|
||||
// OrcOfficer and OrcSoldier are defined similarly as OrcCommander
|
||||
|
||||
```
|
||||
|
||||
Then we have the Orc King who gives the orders and forms the chain
|
||||
|
||||
```
|
||||
public class OrcKing {
|
||||
RequestHandler chain;
|
||||
|
||||
public OrcKing() {
|
||||
buildChain();
|
||||
}
|
||||
|
||||
private void buildChain() {
|
||||
chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null)));
|
||||
}
|
||||
|
||||
public void makeRequest(Request req) {
|
||||
chain.handleRequest(req);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then it is used as follows
|
||||
|
||||
```
|
||||
OrcKing king = new OrcKing();
|
||||
king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle"
|
||||
king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner"
|
||||
king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax"
|
||||
```
|
||||
|
||||
## Applicability
|
||||
Use Chain of Responsibility when
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 30 KiB |
@ -1,109 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||
<class id="1" language="java" name="com.iluwatar.chain.Request" project="chain"
|
||||
file="/chain/src/main/java/com/iluwatar/chain/Request.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="196" width="228" x="168" y="182"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="2" language="java" name="com.iluwatar.chain.OrcOfficer" project="chain"
|
||||
file="/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="194" x="168" y="609"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwatar.chain.OrcCommander" project="chain"
|
||||
file="/chain/src/main/java/com/iluwatar/chain/OrcCommander.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="217" x="402" y="609"/>
|
||||
<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="4" language="java" name="com.iluwatar.chain.RequestHandler" project="chain"
|
||||
file="/chain/src/main/java/com/iluwatar/chain/RequestHandler.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="141" width="218" x="451" y="418"/>
|
||||
<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="5" language="java" name="com.iluwatar.chain.OrcSoldier" project="chain"
|
||||
file="/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="194" x="659" y="609"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="6" language="java" name="com.iluwatar.chain.OrcKing" project="chain"
|
||||
file="/chain/src/main/java/com/iluwatar/chain/OrcKing.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="124" width="188" x="451" y="182"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<enumeration id="7" language="java" name="com.iluwatar.chain.RequestType" project="chain"
|
||||
file="/chain/src/main/java/com/iluwatar/chain/RequestType.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="142" width="243" x="168" y="418"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</enumeration>
|
||||
<association id="8">
|
||||
<end type="SOURCE" refId="6" navigable="false">
|
||||
<attribute id="9" name="chain"/>
|
||||
<multiplicity id="10" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="4" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="11">
|
||||
<end type="SOURCE" refId="4" navigable="false">
|
||||
<attribute id="12" name="next"/>
|
||||
<multiplicity id="13" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="4" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<generalization id="14">
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</generalization>
|
||||
<association id="15">
|
||||
<end type="SOURCE" refId="1" navigable="false">
|
||||
<attribute id="16" name="requestType"/>
|
||||
<multiplicity id="17" minimum="0" maximum="1"/>
|
||||
</end>
|
||||
<end type="TARGET" refId="7" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<generalization id="18">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</generalization>
|
||||
<generalization id="19">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</generalization>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
@ -1,61 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.chain {
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class OrcCommander {
|
||||
+ OrcCommander(handler : RequestHandler)
|
||||
+ handleRequest(req : Request)
|
||||
+ toString() : String
|
||||
}
|
||||
class OrcKing {
|
||||
~ chain : RequestHandler
|
||||
+ OrcKing()
|
||||
- buildChain()
|
||||
+ makeRequest(req : Request)
|
||||
}
|
||||
class OrcOfficer {
|
||||
+ OrcOfficer(handler : RequestHandler)
|
||||
+ handleRequest(req : Request)
|
||||
+ toString() : String
|
||||
}
|
||||
class OrcSoldier {
|
||||
+ OrcSoldier(handler : RequestHandler)
|
||||
+ handleRequest(req : Request)
|
||||
+ toString() : String
|
||||
}
|
||||
class Request {
|
||||
- handled : boolean
|
||||
- requestDescription : String
|
||||
- requestType : RequestType
|
||||
+ Request(requestType : RequestType, requestDescription : String)
|
||||
+ getRequestDescription() : String
|
||||
+ getRequestType() : RequestType
|
||||
+ isHandled() : boolean
|
||||
+ markHandled()
|
||||
+ toString() : String
|
||||
}
|
||||
abstract class RequestHandler {
|
||||
- LOGGER : Logger {static}
|
||||
- next : RequestHandler
|
||||
+ RequestHandler(next : RequestHandler)
|
||||
+ handleRequest(req : Request)
|
||||
# printHandling(req : Request)
|
||||
+ toString() : String {abstract}
|
||||
}
|
||||
enum RequestType {
|
||||
+ COLLECT_TAX {static}
|
||||
+ DEFEND_CASTLE {static}
|
||||
+ TORTURE_PRISONER {static}
|
||||
+ valueOf(name : String) : RequestType {static}
|
||||
+ values() : RequestType[] {static}
|
||||
}
|
||||
}
|
||||
RequestHandler --> "-next" RequestHandler
|
||||
Request --> "-requestType" RequestType
|
||||
OrcKing --> "-chain" RequestHandler
|
||||
OrcCommander --|> RequestHandler
|
||||
OrcOfficer --|> RequestHandler
|
||||
OrcSoldier --|> RequestHandler
|
||||
@enduml
|
Binary file not shown.
Before Width: | Height: | Size: 60 KiB |
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>chain</artifactId>
|
||||
<dependencies>
|
||||
|
@ -85,9 +85,7 @@
|
||||
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
||||
</module>
|
||||
<module name="NeedBraces"/>
|
||||
<module name="LeftCurly">
|
||||
<property name="maxLineLength" value="120"/>
|
||||
</module>
|
||||
<module name="LeftCurly"/>
|
||||
<module name="RightCurly"/>
|
||||
<module name="RightCurly">
|
||||
<property name="option" value="alone"/>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Command
|
||||
folder: command
|
||||
permalink: /patterns/command/
|
||||
pumlid: DSgn4OCm30NGLM00h3xR25i7vYpXaxx2-g59zugtTgiZcwIFvGHcV8YSdt9qdBbdYDVR88PIRwK-yc6mqyLVtff4FsoR38XRa7Aye3SgMoD1_RkaQvcfumS0
|
||||
categories: Behavioral
|
||||
tags:
|
||||
- Java
|
||||
@ -37,6 +36,10 @@ Use the Command pattern when you want to
|
||||
* implement callback functionality
|
||||
* implement the undo functionality
|
||||
|
||||
## Presentations
|
||||
|
||||
* [Command Pattern](etc/presentation.html)
|
||||
|
||||
## Real world examples
|
||||
|
||||
* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
|
||||
|
@ -1,86 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.command {
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
abstract class Command {
|
||||
+ Command()
|
||||
+ execute(Target) {abstract}
|
||||
+ redo() {abstract}
|
||||
+ toString() : String {abstract}
|
||||
+ undo() {abstract}
|
||||
}
|
||||
class Goblin {
|
||||
+ Goblin()
|
||||
+ toString() : String
|
||||
}
|
||||
class InvisibilitySpell {
|
||||
- target : Target
|
||||
+ InvisibilitySpell()
|
||||
+ execute(target : Target)
|
||||
+ redo()
|
||||
+ toString() : String
|
||||
+ undo()
|
||||
}
|
||||
class ShrinkSpell {
|
||||
- oldSize : Size
|
||||
- target : Target
|
||||
+ ShrinkSpell()
|
||||
+ execute(target : Target)
|
||||
+ redo()
|
||||
+ toString() : String
|
||||
+ undo()
|
||||
}
|
||||
enum Size {
|
||||
+ LARGE {static}
|
||||
+ NORMAL {static}
|
||||
+ SMALL {static}
|
||||
+ UNDEFINED {static}
|
||||
- title : String
|
||||
+ toString() : String
|
||||
+ valueOf(name : String) : Size {static}
|
||||
+ values() : Size[] {static}
|
||||
}
|
||||
abstract class Target {
|
||||
- LOGGER : Logger {static}
|
||||
- size : Size
|
||||
- visibility : Visibility
|
||||
+ Target()
|
||||
+ getSize() : Size
|
||||
+ getVisibility() : Visibility
|
||||
+ printStatus()
|
||||
+ setSize(size : Size)
|
||||
+ setVisibility(visibility : Visibility)
|
||||
+ toString() : String {abstract}
|
||||
}
|
||||
enum Visibility {
|
||||
+ INVISIBLE {static}
|
||||
+ UNDEFINED {static}
|
||||
+ VISIBLE {static}
|
||||
- title : String
|
||||
+ toString() : String
|
||||
+ valueOf(name : String) : Visibility {static}
|
||||
+ values() : Visibility[] {static}
|
||||
}
|
||||
class Wizard {
|
||||
- LOGGER : Logger {static}
|
||||
- redoStack : Deque<Command>
|
||||
- undoStack : Deque<Command>
|
||||
+ Wizard()
|
||||
+ castSpell(command : Command, target : Target)
|
||||
+ redoLastSpell()
|
||||
+ toString() : String
|
||||
+ undoLastSpell()
|
||||
}
|
||||
}
|
||||
Target --> "-size" Size
|
||||
Wizard --> "-undoStack" Command
|
||||
ShrinkSpell --> "-oldSize" Size
|
||||
InvisibilitySpell --> "-target" Target
|
||||
ShrinkSpell --> "-target" Target
|
||||
Target --> "-visibility" Visibility
|
||||
Goblin --|> Target
|
||||
InvisibilitySpell --|> Command
|
||||
ShrinkSpell --|> Command
|
||||
@enduml
|
BIN
command/etc/diagram.png
Normal file
BIN
command/etc/diagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
243
command/etc/presentation.html
Normal file
243
command/etc/presentation.html
Normal file
@ -0,0 +1,243 @@
|
||||
<!--
|
||||
|
||||
The MIT License
|
||||
Copyright (c) 2017 Rodolfo Forte
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Design Patterns - Command Presentation</title>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
|
||||
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
|
||||
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
|
||||
|
||||
body { font-family: 'Droid Serif'; }
|
||||
h1, h2, h3 {
|
||||
font-family: 'Yanone Kaffeesatz';
|
||||
font-weight: normal;
|
||||
}
|
||||
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
|
||||
|
||||
blockquote {
|
||||
border-left: 0.3em solid rgba(0,0,0,0.5);
|
||||
padding: 0 15px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width:100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<textarea id="source">
|
||||
|
||||
class: center, middle
|
||||
|
||||
# Command
|
||||
|
||||
---
|
||||
|
||||
# Also known as
|
||||
|
||||
* Action, Transaction
|
||||
|
||||
---
|
||||
|
||||
# Intent
|
||||
|
||||
* Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
|
||||
|
||||
---
|
||||
|
||||
# Explanation
|
||||
|
||||
* [Wikipedia](https://en.wikipedia.org/wiki/Command_pattern) says:
|
||||
> In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters.
|
||||
|
||||
<br />
|
||||
|
||||
* In plain words:
|
||||
|
||||
* Enable the construction of components that are able to delegate, sequence or execute method calls at a time of their choosing;
|
||||
|
||||
---
|
||||
|
||||
# Explanation
|
||||
|
||||
Four terms always associated with the pattern:
|
||||
|
||||
* Command
|
||||
* Object that knows about the receiver and invokes a method of the receiver;
|
||||
|
||||
* Receiver
|
||||
* Object that does the work;
|
||||
|
||||
* Invoker
|
||||
* Knows how to execute a command, and optionally does the bookkeeping about the command execution;
|
||||
|
||||
* Client
|
||||
* Decides which commands to execute at which points, passing the command object to the invoker object;
|
||||
|
||||
---
|
||||
|
||||
# Example
|
||||
|
||||
In our example, a Wizard can cast spells on targets.
|
||||
|
||||
* Spell will be the command (implements the Command interface);
|
||||
* Goblin (a Target object) will be the receiver;
|
||||
* Wizard will be the invoker;
|
||||
* App will be the client;
|
||||
|
||||
```
|
||||
|
||||
//App.java
|
||||
public static void main(String[] args) {
|
||||
Wizard wizard = new Wizard();
|
||||
Goblin goblin = new Goblin();
|
||||
goblin.printStatus(); //Goblin, [size=normal] [visibility=visible]
|
||||
|
||||
wizard.castSpell(new ShrinkSpell(), goblin);
|
||||
wizard.castSpell(new InvisibilitySpell(), goblin);
|
||||
|
||||
goblin.printStatus(); //Goblin, [size=small] [visibility=invisible]
|
||||
|
||||
wizard.undoLastSpell();
|
||||
|
||||
goblin.printStatus(); //Goblin, [size=small] [visibility=visible]
|
||||
|
||||
wizard.redoLastSpell();
|
||||
goblin.printStatus(); //Goblin, [size=small] [visibility=invisible]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Diagram
|
||||
|
||||
.center[]
|
||||
|
||||
|
||||
---
|
||||
|
||||
# Applicability
|
||||
|
||||
Use the Command pattern when you want to:
|
||||
|
||||
* Parameterize objects by an action to perform;
|
||||
* You can express such parameterization in a procedural language with a callback function, that is, a function that's registered somewhere to be called at a later point;
|
||||
|
||||
* Commands are an object-oriented replacement for callbacks;
|
||||
|
||||
<br />
|
||||
|
||||
* Specify, queue, and execute requests at different times;
|
||||
* A Command object can have a lifetime independent of the original request;
|
||||
|
||||
* If the receiver of a request can be represented in an address space-independent way, then you can transfer a command object for the request to a different process and fulfill the request there;
|
||||
|
||||
---
|
||||
|
||||
# Applicability
|
||||
|
||||
Use the Command pattern when you want to:
|
||||
|
||||
* Support undo;
|
||||
* The Command's execute() operation can store state for reversing its effects in the command itself;
|
||||
|
||||
* The Command interface must have an added unexecute() operation that reverses the effects of a previous call to execute;
|
||||
|
||||
* Executed commands are stored in a history list;
|
||||
|
||||
* Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling unexecute() and execute(), respectively;
|
||||
|
||||
---
|
||||
|
||||
# Applicability
|
||||
|
||||
Use the Command pattern when you want to:
|
||||
|
||||
* Support logging changes so that they can be reapplied in case of a system crash;
|
||||
* By augmenting the Command interface with load() and store() operations, you can keep a persistent log of changes;
|
||||
|
||||
* Recovering from a crash involves reloading logged commands from disk and re-executing them with the execute operation;
|
||||
|
||||
---
|
||||
|
||||
# Applicability
|
||||
|
||||
Use the Command pattern when you want to:
|
||||
|
||||
* Structure a system around high-level operations build on primitive operations;
|
||||
* Such a structure is common in information systems that support transactions;
|
||||
|
||||
* A transaction encapsulates a set of changes to data;
|
||||
|
||||
* The Command pattern offers a way to model transactions;
|
||||
|
||||
* Commands have a common interface, letting you invoke all transactions the same way;
|
||||
|
||||
* The pattern also makes it easy to extend the system with new transactions
|
||||
|
||||
---
|
||||
|
||||
# Use Cases
|
||||
|
||||
* To keep a history of requests;
|
||||
|
||||
* Implement callback functionality;
|
||||
|
||||
* Implement the undo functionality;
|
||||
|
||||
---
|
||||
|
||||
# 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)
|
||||
|
||||
[javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html)
|
||||
|
||||
---
|
||||
|
||||
# Credits
|
||||
|
||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)
|
||||
|
||||
---
|
||||
|
||||
# Tutorials
|
||||
|
||||
* Source code http://java-design-patterns.com/patterns/command/
|
||||
|
||||
</textarea>
|
||||
<script src="https://gnab.github.io/remark/downloads/remark-latest.min.js">
|
||||
</script>
|
||||
<script>
|
||||
var slideshow = remark.create();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>command</artifactId>
|
||||
<dependencies>
|
||||
|
@ -29,7 +29,7 @@ package com.iluwatar.command;
|
||||
*/
|
||||
public enum Size {
|
||||
|
||||
SMALL("small"), NORMAL("normal"), LARGE("large"), UNDEFINED("");
|
||||
SMALL("small"), NORMAL("normal");
|
||||
|
||||
private String title;
|
||||
|
||||
|
@ -29,7 +29,7 @@ package com.iluwatar.command;
|
||||
*/
|
||||
public enum Visibility {
|
||||
|
||||
VISIBLE("visible"), INVISIBLE("invisible"), UNDEFINED("");
|
||||
VISIBLE("visible"), INVISIBLE("invisible");
|
||||
|
||||
private String title;
|
||||
|
||||
|
@ -40,7 +40,9 @@ public class Wizard {
|
||||
private Deque<Command> undoStack = new LinkedList<>();
|
||||
private Deque<Command> redoStack = new LinkedList<>();
|
||||
|
||||
public Wizard() {}
|
||||
public Wizard() {
|
||||
// comment to ignore sonar issue: LEVEL critical
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast spell
|
||||
|
@ -81,13 +81,13 @@ public class CommandTest {
|
||||
* @param goblin a goblin object whose state is to be verified against other parameters
|
||||
* @param expectedName expectedName of the goblin
|
||||
* @param expectedSize expected size of the goblin
|
||||
* @param expectedVisibilty exepcted visibility of the goblin
|
||||
* @param expectedVisibility expected visibility of the goblin
|
||||
*/
|
||||
private void verifyGoblin(Goblin goblin, String expectedName, Size expectedSize,
|
||||
Visibility expectedVisibilty) {
|
||||
Visibility expectedVisibility) {
|
||||
assertEquals("Goblin's name must be same as expectedName", expectedName, goblin.toString());
|
||||
assertEquals("Goblin's size must be same as expectedSize", expectedSize, goblin.getSize());
|
||||
assertEquals("Goblin's visibility must be same as expectedVisibility", expectedVisibilty,
|
||||
assertEquals("Goblin's visibility must be same as expectedVisibility", expectedVisibility,
|
||||
goblin.getVisibility());
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Composite
|
||||
folder: composite
|
||||
permalink: /patterns/composite/
|
||||
pumlid: HSf13eCm30NHgy01YFUzZGaM62LEP7-NwvTTT_EaMTLgoqFIst81Cpv4payv5LVk6U9r6CHGwkYaBHy6EztyvUsGqDEsoO2u1NMED-WTvmY5aA3-LT9xcTdR3m00
|
||||
categories: Structural
|
||||
tags:
|
||||
- Java
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>composite</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,7 @@ layout: pattern
|
||||
title: Converter
|
||||
folder: converter
|
||||
permalink: /patterns/converter/
|
||||
categories:
|
||||
categories: Business Tier
|
||||
tags:
|
||||
- Java
|
||||
- Difficulty-Beginner
|
||||
|
@ -1,49 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.converter {
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class Converter<T, U> {
|
||||
- fromDto : Function<T, U>
|
||||
- fromEntity : Function<U, T>
|
||||
+ Converter<T, U>(fromDto : Function<T, U>, fromEntity : Function<U, T>)
|
||||
+ convertFromDto(userDto : T) : U
|
||||
+ convertFromEntity(user : U) : T
|
||||
+ createFromDtos(dtoUsers : Collection<T>) : List<U>
|
||||
+ createFromEntities(users : Collection<U>) : List<T>
|
||||
}
|
||||
class User {
|
||||
- firstName : String
|
||||
- isActive : boolean
|
||||
- lastName : String
|
||||
- userId : String
|
||||
+ User(firstName : String, lastName : String, isActive : boolean, userId : String)
|
||||
+ equals(o : Object) : boolean
|
||||
+ getFirstName() : String
|
||||
+ getLastName() : String
|
||||
+ getUserId() : String
|
||||
+ hashCode() : int
|
||||
+ isActive() : boolean
|
||||
+ toString() : String
|
||||
}
|
||||
class UserConverter {
|
||||
+ UserConverter()
|
||||
}
|
||||
class UserDto {
|
||||
- email : String
|
||||
- firstName : String
|
||||
- isActive : boolean
|
||||
- lastName : String
|
||||
+ UserDto(firstName : String, lastName : String, isActive : boolean, email : String)
|
||||
+ equals(o : Object) : boolean
|
||||
+ getEmail() : String
|
||||
+ getFirstName() : String
|
||||
+ getLastName() : String
|
||||
+ hashCode() : int
|
||||
+ isActive() : boolean
|
||||
+ toString() : String
|
||||
}
|
||||
}
|
||||
UserConverter --|> Converter
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<dependencies>
|
||||
|
@ -41,10 +41,7 @@ public class App {
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Converter<UserDto, User> userConverter = new Converter<>(
|
||||
userDto -> new User(userDto.getFirstName(), userDto.getLastName(), userDto.isActive(),
|
||||
userDto.getEmail()),
|
||||
user -> new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), user.getUserId()));
|
||||
Converter<UserDto, User> userConverter = new UserConverter();
|
||||
|
||||
UserDto dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com");
|
||||
User user = userConverter.convertFromDto(dtoUser);
|
||||
|
@ -68,7 +68,7 @@ public class Converter<T, U> {
|
||||
/**
|
||||
* @param dtoUsers collection of DTO entities
|
||||
* @return List of domain representation of provided entities retrieved by
|
||||
* mapping each of them with the convertion function
|
||||
* mapping each of them with the conversion function
|
||||
*/
|
||||
public final List<U> createFromDtos(final Collection<T> dtoUsers) {
|
||||
return dtoUsers.stream().map(this::convertFromDto).collect(Collectors.toList());
|
||||
@ -77,7 +77,7 @@ public class Converter<T, U> {
|
||||
/**
|
||||
* @param users collection of domain entities
|
||||
* @return List of domain representation of provided entities retrieved by
|
||||
* mapping each of them with the convertion function
|
||||
* mapping each of them with the conversion function
|
||||
*/
|
||||
public final List<T> createFromEntities(final Collection<U> users) {
|
||||
return users.stream().map(this::convertFromEntity).collect(Collectors.toList());
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: CQRS
|
||||
folder: cqrs
|
||||
permalink: /patterns/cqrs/
|
||||
pumlid: 7SPR4a0m3030gt00pR_RH6I8QQFouFgC_TfHb6gkd5Q7FQBx363ub4rYpoMTZKuDrYXqDX37HIuuyCPfPPTDfuuHREhGqBy0NUR0GNzAMYizMtq1
|
||||
categories: Architectural
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,124 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.cqrs.util {
|
||||
class HibernateUtil {
|
||||
- LOGGER : Logger {static}
|
||||
- SESSIONFACTORY : SessionFactory {static}
|
||||
+ HibernateUtil()
|
||||
- buildSessionFactory() : SessionFactory {static}
|
||||
+ getSessionFactory() : SessionFactory {static}
|
||||
}
|
||||
}
|
||||
package com.iluwatar.cqrs.app {
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
}
|
||||
package com.iluwatar.cqrs.dto {
|
||||
class Author {
|
||||
- email : String
|
||||
- name : String
|
||||
- username : String
|
||||
+ Author()
|
||||
+ Author(name : String, email : String, username : String)
|
||||
+ equals(obj : Object) : boolean
|
||||
+ getEmail() : String
|
||||
+ getName() : String
|
||||
+ getUsername() : String
|
||||
+ hashCode() : int
|
||||
+ toString() : String
|
||||
}
|
||||
class Book {
|
||||
- price : double
|
||||
- title : String
|
||||
+ Book()
|
||||
+ Book(title : String, price : double)
|
||||
+ equals(obj : Object) : boolean
|
||||
+ getPrice() : double
|
||||
+ getTitle() : String
|
||||
+ hashCode() : int
|
||||
+ toString() : String
|
||||
}
|
||||
}
|
||||
package com.iluwatar.cqrs.commandes {
|
||||
class CommandServiceImpl {
|
||||
- sessionFactory : SessionFactory
|
||||
+ CommandServiceImpl()
|
||||
+ authorCreated(username : String, name : String, email : String)
|
||||
+ authorEmailUpdated(username : String, email : String)
|
||||
+ authorNameUpdated(username : String, name : String)
|
||||
+ authorUsernameUpdated(oldUsername : String, newUsername : String)
|
||||
+ bookAddedToAuthor(title : String, price : double, username : String)
|
||||
+ bookPriceUpdated(title : String, price : double)
|
||||
+ bookTitleUpdated(oldTitle : String, newTitle : String)
|
||||
- getAuthorByUsername(username : String) : Author
|
||||
- getBookByTitle(title : String) : Book
|
||||
}
|
||||
interface ICommandService {
|
||||
+ authorCreated(String, String, String) {abstract}
|
||||
+ authorEmailUpdated(String, String) {abstract}
|
||||
+ authorNameUpdated(String, String) {abstract}
|
||||
+ authorUsernameUpdated(String, String) {abstract}
|
||||
+ bookAddedToAuthor(String, double, String) {abstract}
|
||||
+ bookPriceUpdated(String, double) {abstract}
|
||||
+ bookTitleUpdated(String, String) {abstract}
|
||||
}
|
||||
}
|
||||
package com.iluwatar.cqrs.queries {
|
||||
interface IQueryService {
|
||||
+ getAuthorBooks(String) : List<Book> {abstract}
|
||||
+ getAuthorBooksCount(String) : BigInteger {abstract}
|
||||
+ getAuthorByUsername(String) : Author {abstract}
|
||||
+ getAuthorsCount() : BigInteger {abstract}
|
||||
+ getBook(String) : Book {abstract}
|
||||
}
|
||||
class QueryServiceImpl {
|
||||
- sessionFactory : SessionFactory
|
||||
+ QueryServiceImpl()
|
||||
+ getAuthorBooks(username : String) : List<Book>
|
||||
+ getAuthorBooksCount(username : String) : BigInteger
|
||||
+ getAuthorByUsername(username : String) : Author
|
||||
+ getAuthorsCount() : BigInteger
|
||||
+ getBook(title : String) : Book
|
||||
}
|
||||
}
|
||||
package com.iluwatar.cqrs.domain.model {
|
||||
class Author {
|
||||
- email : String
|
||||
- id : long
|
||||
- name : String
|
||||
- username : String
|
||||
# Author()
|
||||
+ Author(username : String, name : String, email : String)
|
||||
+ getEmail() : String
|
||||
+ getId() : long
|
||||
+ getName() : String
|
||||
+ getUsername() : String
|
||||
+ setEmail(email : String)
|
||||
+ setId(id : long)
|
||||
+ setName(name : String)
|
||||
+ setUsername(username : String)
|
||||
+ toString() : String
|
||||
}
|
||||
class Book {
|
||||
- author : Author
|
||||
- id : long
|
||||
- price : double
|
||||
- title : String
|
||||
# Book()
|
||||
+ Book(title : String, price : double, author : Author)
|
||||
+ getAuthor() : Author
|
||||
+ getId() : long
|
||||
+ getPrice() : double
|
||||
+ getTitle() : String
|
||||
+ setAuthor(author : Author)
|
||||
+ setId(id : long)
|
||||
+ setPrice(price : double)
|
||||
+ setTitle(title : String)
|
||||
+ toString() : String
|
||||
}
|
||||
}
|
||||
Book --> "-author" Author
|
||||
CommandServiceImpl ..|> ICommandService
|
||||
QueryServiceImpl ..|> IQueryService
|
||||
@enduml
|
@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>cqrs</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Data Access Object
|
||||
folder: dao
|
||||
permalink: /patterns/dao/
|
||||
pumlid: 5SR14OKW30N0LhG0oVrt4o6ZE12Ov4NR_thQNQlc5aN2sd82qtz4naywAixOmyNoK8WYvT6fjdWOR7JnpLiHhuTkam4nTUhiRwZm847-J64zpUZj3m00
|
||||
categories: Persistence Tier
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,66 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.dao {
|
||||
class App {
|
||||
- DB_URL : String {static}
|
||||
- log : Logger {static}
|
||||
+ App()
|
||||
- addCustomers(customerDao : CustomerDao) {static}
|
||||
- createDataSource() : DataSource {static}
|
||||
- createSchema(dataSource : DataSource) {static}
|
||||
- deleteSchema(dataSource : DataSource) {static}
|
||||
+ generateSampleCustomers() : List<Customer> {static}
|
||||
+ main(args : String[]) {static}
|
||||
- performOperationsUsing(customerDao : CustomerDao) {static}
|
||||
}
|
||||
class Customer {
|
||||
- firstName : String
|
||||
- id : int
|
||||
- lastName : String
|
||||
+ Customer(id : int, firstName : String, lastName : String)
|
||||
+ equals(that : Object) : boolean
|
||||
+ getFirstName() : String
|
||||
+ getId() : int
|
||||
+ getLastName() : String
|
||||
+ hashCode() : int
|
||||
+ setFirstName(firstName : String)
|
||||
+ setId(id : int)
|
||||
+ setLastName(lastName : String)
|
||||
+ toString() : String
|
||||
}
|
||||
interface CustomerDao {
|
||||
+ add(Customer) : boolean {abstract}
|
||||
+ delete(Customer) : boolean {abstract}
|
||||
+ getAll() : Stream<Customer> {abstract}
|
||||
+ getById(int) : Optional<Customer> {abstract}
|
||||
+ update(Customer) : boolean {abstract}
|
||||
}
|
||||
class CustomerSchemaSql {
|
||||
+ CREATE_SCHEMA_SQL : String {static}
|
||||
+ DELETE_SCHEMA_SQL : String {static}
|
||||
- CustomerSchemaSql()
|
||||
}
|
||||
class DbCustomerDao {
|
||||
- dataSource : DataSource
|
||||
+ DbCustomerDao(dataSource : DataSource)
|
||||
+ add(customer : Customer) : boolean
|
||||
- createCustomer(resultSet : ResultSet) : Customer
|
||||
+ delete(customer : Customer) : boolean
|
||||
+ getAll() : Stream<Customer>
|
||||
+ getById(id : int) : Optional<Customer>
|
||||
- getConnection() : Connection
|
||||
- mutedClose(connection : Connection)
|
||||
+ update(customer : Customer) : boolean
|
||||
}
|
||||
class InMemoryCustomerDao {
|
||||
- idToCustomer : Map<Integer, Customer>
|
||||
+ InMemoryCustomerDao()
|
||||
+ add(customer : Customer) : boolean
|
||||
+ delete(customer : Customer) : boolean
|
||||
+ getAll() : Stream<Customer>
|
||||
+ getById(id : int) : Optional<Customer>
|
||||
+ update(customer : Customer) : boolean
|
||||
}
|
||||
}
|
||||
DbCustomerDao ..|> CustomerDao
|
||||
InMemoryCustomerDao ..|> CustomerDao
|
||||
@enduml
|
@ -30,7 +30,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>dao</artifactId>
|
||||
|
||||
|
43
dao/src/main/java/com/iluwatar/dao/CustomException.java
Normal file
43
dao/src/main/java/com/iluwatar/dao/CustomException.java
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* Custom exception
|
||||
*
|
||||
*/
|
||||
public class CustomException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CustomException() {}
|
||||
|
||||
public CustomException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CustomException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -36,12 +36,16 @@ import java.util.stream.StreamSupport;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* An implementation of {@link CustomerDao} that persists customers in RDBMS.
|
||||
*
|
||||
*/
|
||||
public class DbCustomerDao implements CustomerDao {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(DbCustomerDao.class);
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
/**
|
||||
@ -79,12 +83,12 @@ public class DbCustomerDao implements CustomerDao {
|
||||
action.accept(createCustomer(resultSet));
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new RuntimeException(e); // NOSONAR
|
||||
}
|
||||
}
|
||||
}, false).onClose(() -> mutedClose(connection, statement, resultSet));
|
||||
} catch (SQLException e) {
|
||||
throw new Exception(e.getMessage(), e);
|
||||
throw new CustomException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +102,7 @@ public class DbCustomerDao implements CustomerDao {
|
||||
statement.close();
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.info("Exception thrown " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,19 +117,26 @@ public class DbCustomerDao implements CustomerDao {
|
||||
*/
|
||||
@Override
|
||||
public Optional<Customer> getById(int id) throws Exception {
|
||||
|
||||
ResultSet resultSet = null;
|
||||
|
||||
try (Connection connection = getConnection();
|
||||
PreparedStatement statement =
|
||||
connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
|
||||
|
||||
statement.setInt(1, id);
|
||||
ResultSet resultSet = statement.executeQuery();
|
||||
resultSet = statement.executeQuery();
|
||||
if (resultSet.next()) {
|
||||
return Optional.of(createCustomer(resultSet));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
throw new Exception(ex.getMessage(), ex);
|
||||
throw new CustomException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
if (resultSet != null) {
|
||||
resultSet.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +158,7 @@ public class DbCustomerDao implements CustomerDao {
|
||||
statement.execute();
|
||||
return true;
|
||||
} catch (SQLException ex) {
|
||||
throw new Exception(ex.getMessage(), ex);
|
||||
throw new CustomException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +175,7 @@ public class DbCustomerDao implements CustomerDao {
|
||||
statement.setInt(3, customer.getId());
|
||||
return statement.executeUpdate() > 0;
|
||||
} catch (SQLException ex) {
|
||||
throw new Exception(ex.getMessage(), ex);
|
||||
throw new CustomException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,7 +190,7 @@ public class DbCustomerDao implements CustomerDao {
|
||||
statement.setInt(1, customer.getId());
|
||||
return statement.executeUpdate() > 0;
|
||||
} catch (SQLException ex) {
|
||||
throw new Exception(ex.getMessage(), ex);
|
||||
throw new CustomException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,77 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.databus {
|
||||
class AbstractDataType {
|
||||
- dataBus : DataBus
|
||||
+ AbstractDataType()
|
||||
+ getDataBus() : DataBus
|
||||
+ setDataBus(dataBus : DataBus)
|
||||
}
|
||||
~class App {
|
||||
- log : Logger {static}
|
||||
~ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class DataBus {
|
||||
- INSTANCE : DataBus {static}
|
||||
- listeners : Set<Member>
|
||||
+ DataBus()
|
||||
+ getInstance() : DataBus {static}
|
||||
+ publish(event : DataType)
|
||||
+ subscribe(member : Member)
|
||||
+ unsubscribe(member : Member)
|
||||
}
|
||||
interface DataType {
|
||||
+ getDataBus() : DataBus {abstract}
|
||||
+ setDataBus(DataBus) {abstract}
|
||||
}
|
||||
interface Member {
|
||||
+ accept(DataType) {abstract}
|
||||
}
|
||||
}
|
||||
package com.iluwatar.databus.data {
|
||||
class MessageData {
|
||||
- message : String
|
||||
+ MessageData(message : String)
|
||||
+ getMessage() : String
|
||||
+ of(message : String) : DataType {static}
|
||||
}
|
||||
class StartingData {
|
||||
- when : LocalDateTime
|
||||
+ StartingData(when : LocalDateTime)
|
||||
+ getWhen() : LocalDateTime
|
||||
+ of(when : LocalDateTime) : DataType {static}
|
||||
}
|
||||
class StoppingData {
|
||||
- when : LocalDateTime
|
||||
+ StoppingData(when : LocalDateTime)
|
||||
+ getWhen() : LocalDateTime
|
||||
+ of(when : LocalDateTime) : DataType {static}
|
||||
}
|
||||
}
|
||||
package com.iluwatar.databus.members {
|
||||
class CounterMember {
|
||||
- log : Logger {static}
|
||||
- name : String
|
||||
+ CounterMember(name : String)
|
||||
+ accept(data : DataType)
|
||||
- handleEvent(data : MessageData)
|
||||
}
|
||||
class StatusMember {
|
||||
- id : int
|
||||
- log : Logger {static}
|
||||
+ StatusMember(id : int)
|
||||
+ accept(data : DataType)
|
||||
- handleEvent(data : StartingData)
|
||||
- handleEvent(data : StoppingData)
|
||||
}
|
||||
}
|
||||
AbstractDataType --> "-dataBus" DataBus
|
||||
DataBus --> "-INSTANCE" DataBus
|
||||
DataBus --> "-listeners" Member
|
||||
AbstractDataType ..|> DataType
|
||||
MessageData --|> AbstractDataType
|
||||
StartingData --|> AbstractDataType
|
||||
StoppingData --|> AbstractDataType
|
||||
CounterMember ..|> Member
|
||||
StatusMember ..|> Member
|
||||
@enduml
|
@ -33,7 +33,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>data-bus</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Data Mapper
|
||||
folder: data-mapper
|
||||
permalink: /patterns/data-mapper/
|
||||
pumlid: JShB3OGm303HLg20nFVjnYGM1CN6ycTfVtFSsnjfzY5jPgUqkLqHwXy0mxUU8wuyqidQ8q4IjJqCO-QBWGOtVh5qyd5AKOmW4mT6Nu2-ZiAekapH_hkcSTNa-GC0
|
||||
categories: Persistence Tier
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,42 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.datamapper {
|
||||
class App {
|
||||
- log : Logger {static}
|
||||
- App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class Student {
|
||||
- grade : char
|
||||
- name : String
|
||||
- serialVersionUID : long {static}
|
||||
- studentId : int
|
||||
+ Student(studentId : int, name : String, grade : char)
|
||||
+ equals(inputObject : Object) : boolean
|
||||
+ getGrade() : char
|
||||
+ getName() : String
|
||||
+ getStudentId() : int
|
||||
+ hashCode() : int
|
||||
+ setGrade(grade : char)
|
||||
+ setName(name : String)
|
||||
+ setStudentId(studentId : int)
|
||||
+ toString() : String
|
||||
}
|
||||
interface StudentDataMapper {
|
||||
+ delete(Student) {abstract}
|
||||
+ find(int) : Optional<Student> {abstract}
|
||||
+ insert(Student) {abstract}
|
||||
+ update(Student) {abstract}
|
||||
}
|
||||
class StudentDataMapperImpl {
|
||||
- students : List<Student>
|
||||
+ StudentDataMapperImpl()
|
||||
+ delete(studentToBeDeleted : Student)
|
||||
+ find(studentId : int) : Optional<Student>
|
||||
+ getStudents() : List<Student>
|
||||
+ insert(studentToBeInserted : Student)
|
||||
+ update(studentToBeUpdated : Student)
|
||||
}
|
||||
}
|
||||
StudentDataMapperImpl --> "-students" Student
|
||||
StudentDataMapperImpl ..|> StudentDataMapper
|
||||
@enduml
|
@ -28,7 +28,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>data-mapper</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Data Transfer Object
|
||||
folder: data-transfer-object
|
||||
permalink: /patterns/data-transfer-object/
|
||||
pumlid: RSh14SCW30NHLk82GFTq8uDYum71I5zn-t41kUtCswrfwL4bhBzEOFcRoFZEHyCPUxXOcGfHv387jHutWuqk_dAguktGj1WGKwV1_WJLvqWmLl-8fRbVKa22yXTosCWhHly1
|
||||
categories: Architectural
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,26 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.datatransfer {
|
||||
class CustomerClientApp {
|
||||
+ CustomerClientApp()
|
||||
+ main(args : String[]) {static}
|
||||
- printCustomerDetails(allCustomers : List<CustomerDto>) {static}
|
||||
}
|
||||
class CustomerDto {
|
||||
- firstName : String
|
||||
- id : String
|
||||
- lastName : String
|
||||
+ CustomerDto(id : String, firstName : String, lastName : String)
|
||||
+ getFirstName() : String
|
||||
+ getId() : String
|
||||
+ getLastName() : String
|
||||
}
|
||||
class CustomerResource {
|
||||
- customers : List<CustomerDto>
|
||||
+ CustomerResource(customers : List<CustomerDto>)
|
||||
+ delete(customerId : String)
|
||||
+ getAllCustomers() : List<CustomerDto>
|
||||
+ save(customer : CustomerDto)
|
||||
}
|
||||
}
|
||||
CustomerResource --> "-customers" CustomerDto
|
||||
@enduml
|
@ -28,7 +28,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>data-transfer-object</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Decorator
|
||||
folder: decorator
|
||||
permalink: /patterns/decorator/
|
||||
pumlid: HSV14SCm20J0Lk82BFxf1YF6LaP26ZZizfDVVhjRC-bPDRs_Bc35cyZvAMV3bKU6kao36ehCGQtdms2d3z-yLursshuOKBUWmV43LPNfZEcaaFzA-YWhH_y2
|
||||
categories: Structural
|
||||
tags:
|
||||
- Java
|
||||
@ -35,7 +34,7 @@ Wikipedia says
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
Lets take the troll example. First of all we have a simple troll implementing the troll interface
|
||||
Let's take the troll example. First of all we have a simple troll implementing the troll interface
|
||||
|
||||
```
|
||||
public interface Troll {
|
||||
@ -105,9 +104,9 @@ troll.attack(); // The troll tries to grab you!
|
||||
troll.fleeBattle(); // The troll shrieks in horror and runs away!
|
||||
|
||||
// change the behavior of the simple troll by adding a decorator
|
||||
Troll clubbed = new ClubbedTroll(troll);
|
||||
clubbed.attack(); // The troll tries to grab you! The troll swings at you with a club!
|
||||
clubbed.fleeBattle(); // The troll shrieks in horror and runs away!
|
||||
troll = new ClubbedTroll(troll);
|
||||
troll.attack(); // The troll tries to grab you! The troll swings at you with a club!
|
||||
troll.fleeBattle(); // The troll shrieks in horror and runs away!
|
||||
```
|
||||
|
||||
## Applicability
|
||||
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>decorator</artifactId>
|
||||
<dependencies>
|
||||
|
@ -57,9 +57,9 @@ public class App {
|
||||
|
||||
// change the behavior of the simple troll by adding a decorator
|
||||
LOGGER.info("A troll with huge club surprises you.");
|
||||
Troll clubbed = new ClubbedTroll(troll);
|
||||
clubbed.attack();
|
||||
clubbed.fleeBattle();
|
||||
LOGGER.info("Clubbed troll power {}.\n", clubbed.getAttackPower());
|
||||
troll = new ClubbedTroll(troll);
|
||||
troll.attack();
|
||||
troll.fleeBattle();
|
||||
LOGGER.info("Clubbed troll power {}.\n", troll.getAttackPower());
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Delegation
|
||||
folder: delegation
|
||||
permalink: /patterns/delegation/
|
||||
pumlid: JSV14GCX20NGLf82LkxfXbN69OFeu2VRVdBCxRsdUhLiac6F2rZxHHHybwwuyimjKQT37ANEGMfvCpZepHy-ccpjVYm697pJuFq3DJ7f39rEWlhNaZ7Aoc5V
|
||||
categories: Behavioral
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,39 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.delegation.simple.printers {
|
||||
class CanonPrinter {
|
||||
- LOGGER : Logger {static}
|
||||
+ CanonPrinter()
|
||||
+ print(message : String)
|
||||
}
|
||||
class EpsonPrinter {
|
||||
- LOGGER : Logger {static}
|
||||
+ EpsonPrinter()
|
||||
+ print(message : String)
|
||||
}
|
||||
class HpPrinter {
|
||||
- LOGGER : Logger {static}
|
||||
+ HpPrinter()
|
||||
+ print(message : String)
|
||||
}
|
||||
}
|
||||
package com.iluwatar.delegation.simple {
|
||||
class App {
|
||||
+ MESSAGE_TO_PRINT : String {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
interface Printer {
|
||||
+ print(String) {abstract}
|
||||
}
|
||||
class PrinterController {
|
||||
- printer : Printer
|
||||
+ PrinterController(printer : Printer)
|
||||
+ print(message : String)
|
||||
}
|
||||
}
|
||||
PrinterController --> "-printer" Printer
|
||||
PrinterController ..|> Printer
|
||||
CanonPrinter ..|> Printer
|
||||
EpsonPrinter ..|> Printer
|
||||
HpPrinter ..|> Printer
|
||||
@enduml
|
@ -30,7 +30,7 @@
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Dependency Injection
|
||||
folder: dependency-injection
|
||||
permalink: /patterns/dependency-injection/
|
||||
pumlid: RSdB3SCW303GLPe1mFTkunWhSGG6-PEesxS3zFQajubIpyPf_NL6B7y363xra3XpJsUZgS4QbUO0wVbWeC65DvR6BeUMXH5iwZ3GVu36YxMnqgU8NamXKu63_aPD6tNbw5y0
|
||||
categories: Behavioral
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,49 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.dependency.injection {
|
||||
class AdvancedWizard {
|
||||
- tobacco : Tobacco
|
||||
+ AdvancedWizard(tobacco : Tobacco)
|
||||
+ smoke()
|
||||
}
|
||||
class App {
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class GuiceWizard {
|
||||
- tobacco : Tobacco
|
||||
+ GuiceWizard(tobacco : Tobacco)
|
||||
+ smoke()
|
||||
}
|
||||
class OldTobyTobacco {
|
||||
+ OldTobyTobacco()
|
||||
}
|
||||
class RivendellTobacco {
|
||||
+ RivendellTobacco()
|
||||
}
|
||||
class SecondBreakfastTobacco {
|
||||
+ SecondBreakfastTobacco()
|
||||
}
|
||||
class SimpleWizard {
|
||||
- tobacco : OldTobyTobacco
|
||||
+ SimpleWizard()
|
||||
+ smoke()
|
||||
}
|
||||
abstract class Tobacco {
|
||||
- LOGGER : Logger {static}
|
||||
+ Tobacco()
|
||||
+ smoke(wizard : Wizard)
|
||||
}
|
||||
interface Wizard {
|
||||
+ smoke() {abstract}
|
||||
}
|
||||
}
|
||||
SimpleWizard --> "-tobacco" OldTobyTobacco
|
||||
AdvancedWizard --> "-tobacco" Tobacco
|
||||
GuiceWizard --> "-tobacco" Tobacco
|
||||
AdvancedWizard ..|> Wizard
|
||||
GuiceWizard ..|> Wizard
|
||||
OldTobyTobacco --|> Tobacco
|
||||
RivendellTobacco --|> Tobacco
|
||||
SecondBreakfastTobacco --|> Tobacco
|
||||
SimpleWizard ..|> Wizard
|
||||
@enduml
|
@ -29,7 +29,7 @@
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>dependency-injection</artifactId>
|
||||
<dependencies>
|
||||
|
@ -3,7 +3,6 @@ layout: pattern
|
||||
title: Double Checked Locking
|
||||
folder: double-checked-locking
|
||||
permalink: /patterns/double-checked-locking/
|
||||
pumlid: TSdH4SCW203GLTe1bFzkGv1J6qGFeLc_MI1_x-wzkv94uJ1vDVUrFm26LwxTMnonsMYgitgcEQ1BNEXeyCKVfiAxLqqBtTbqmy1z0ygCGpXHOpgv99bqTgt0JW-LmqPUCUGF
|
||||
categories: Concurrency
|
||||
tags:
|
||||
- Java
|
||||
|
@ -1,22 +0,0 @@
|
||||
@startuml
|
||||
package com.iluwatar.doublechecked.locking {
|
||||
class App {
|
||||
- LOGGER : Logger {static}
|
||||
+ App()
|
||||
+ main(args : String[]) {static}
|
||||
}
|
||||
class Inventory {
|
||||
- LOGGER : Logger {static}
|
||||
- inventorySize : int
|
||||
- items : List<Item>
|
||||
- lock : Lock
|
||||
+ Inventory(inventorySize : int)
|
||||
+ addItem(item : Item) : boolean
|
||||
+ getItems() : List<Item>
|
||||
}
|
||||
class Item {
|
||||
+ Item()
|
||||
}
|
||||
}
|
||||
Inventory --> "-items" Item
|
||||
@enduml
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user