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://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://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://sonarqube.com/dashboard/index/com.iluwatar%3Ajava-design-patterns)
|
||||||
|
[](https://bestpractices.coreinfrastructure.org/projects/1503)
|
||||||
|
|
||||||
# Introduction
|
# 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
|
title: Abstract Document
|
||||||
folder: abstract-document
|
folder: abstract-document
|
||||||
permalink: /patterns/abstract-document/
|
permalink: /patterns/abstract-document/
|
||||||
pumlid: PSjB3eCm34NHhPG599vtDyQn85L-ifzX-p3lxEf8Twj3MXGDQvyJMFubChxpKN767gucSq07iinEjSNDOACVNvoAUZr6MWoe3QVE_WRnxZ0Mf38b-hkIGlurX_MyehS7
|
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>abstract-document</artifactId>
|
<artifactId>abstract-document</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Abstract Factory
|
title: Abstract Factory
|
||||||
folder: abstract-factory
|
folder: abstract-factory
|
||||||
permalink: /patterns/abstract-factory/
|
permalink: /patterns/abstract-factory/
|
||||||
pumlid: PSZB3OD034NHLa81Czwd6sCC39gVxEUWT1_ssLmTtQLqgR5fM7sTmFGtaV6TZu8prd0r6HtQaMKqAZLk1XjT_E6qgPUZfyc0MdTgx0-8LuUn8ErFXdr98NypXxKyezKV
|
|
||||||
categories: Creational
|
categories: Creational
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
@ -120,6 +119,45 @@ king.getDescription(); // Output: This is the Elven king!
|
|||||||
army.getDescription(); // Output: This is the Elven Army!
|
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
|
## Applicability
|
||||||
Use the Abstract Factory pattern when
|
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.
|
* 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
|
## Real world examples
|
||||||
|
|
||||||
* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)
|
* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)
|
||||||
|
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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>abstract-factory</artifactId>
|
<artifactId>abstract-factory</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -25,6 +25,8 @@ package com.iluwatar.abstractfactory;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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
|
* 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
|
* @param args
|
||||||
* command line args
|
* command line args
|
||||||
@ -104,17 +133,15 @@ public class App {
|
|||||||
App app = new App();
|
App app = new App();
|
||||||
|
|
||||||
LOGGER.info("Elf Kingdom");
|
LOGGER.info("Elf Kingdom");
|
||||||
app.createKingdom(new ElfKingdomFactory());
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||||
LOGGER.info(app.getArmy().getDescription());
|
LOGGER.info(app.getArmy().getDescription());
|
||||||
LOGGER.info(app.getCastle().getDescription());
|
LOGGER.info(app.getCastle().getDescription());
|
||||||
LOGGER.info(app.getKing().getDescription());
|
LOGGER.info(app.getKing().getDescription());
|
||||||
|
|
||||||
LOGGER.info("Orc Kingdom");
|
LOGGER.info("Orc Kingdom");
|
||||||
app.createKingdom(new OrcKingdomFactory());
|
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||||
LOGGER.info(app.getArmy().getDescription());
|
LOGGER.info(app.getArmy().getDescription());
|
||||||
LOGGER.info(app.getCastle().getDescription());
|
LOGGER.info(app.getCastle().getDescription());
|
||||||
LOGGER.info(app.getKing().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.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
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.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -39,8 +42,8 @@ public class AbstractFactoryTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
elfFactory = new ElfKingdomFactory();
|
elfFactory = FactoryMaker.makeFactory(KingdomType.ELF);
|
||||||
orcFactory = new OrcKingdomFactory();
|
orcFactory = FactoryMaker.makeFactory(KingdomType.ORC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Adapter
|
title: Adapter
|
||||||
folder: adapter
|
folder: adapter
|
||||||
permalink: /patterns/adapter/
|
permalink: /patterns/adapter/
|
||||||
pumlid: DSR14S8m30J0Lg20M7-wEMnDOiPMFDA9j0yyUEtUkzMHJTF7xI1NF4GSLzaxZtncgDVJgCPIpobzv0N2vOKtjgRHTziMI7KBcOXl10thfxB-Nz9dMJd71m00
|
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>adapter</artifactId>
|
<artifactId>adapter</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Aggregator Microservices
|
title: Aggregator Microservices
|
||||||
folder: aggregator-microservices
|
folder: aggregator-microservices
|
||||||
permalink: /patterns/aggregator-microservices/
|
permalink: /patterns/aggregator-microservices/
|
||||||
pumlid: JOov3SCm301NIGQGs7iRXYPa1g8ayB7NjuiKwGvtmBrbKC-Tq_hhY5Y-0HXUjKaS-Kbdepc2HrIQ2jBpma23BvvOTdPfeooCO1iEYlu0O6l63MDQKI6Rp-CKOWSE-ey_NzEqhjH-0m00
|
|
||||||
categories: Architectural
|
categories: Architectural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>aggregator-microservices</artifactId>
|
<artifactId>aggregator-microservices</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<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>
|
<parent>
|
||||||
<artifactId>aggregator-microservices</artifactId>
|
<artifactId>aggregator-microservices</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>aggregator-microservices</artifactId>
|
<artifactId>aggregator-microservices</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -29,32 +29,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>aggregator-microservices</artifactId>
|
<artifactId>aggregator-microservices</artifactId>
|
||||||
<packaging>pom</packaging>
|
<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>
|
<modules>
|
||||||
<module>information-microservice</module>
|
<module>information-microservice</module>
|
||||||
<module>aggregator-service</module>
|
<module>aggregator-service</module>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: API Gateway
|
title: API Gateway
|
||||||
folder: api-gateway
|
folder: api-gateway
|
||||||
permalink: /patterns/api-gateway/
|
permalink: /patterns/api-gateway/
|
||||||
pumlid: JSox3SCm303HLP819FRUXg49cO542_nOyFPncUvUSszHwhbpMdyT4TCt0CDLcyIHdtGsEZLOez8vG7ek33JuueLbPvUcPM84cpeCz2S0fvI6mGjluA1_b-Tt2N5D6tNcw3y0
|
|
||||||
categories: Architectural
|
categories: Architectural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>api-gateway</artifactId>
|
<artifactId>api-gateway</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>api-gateway-service</artifactId>
|
<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>
|
<parent>
|
||||||
<artifactId>api-gateway</artifactId>
|
<artifactId>api-gateway</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -29,32 +29,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>api-gateway</artifactId>
|
<artifactId>api-gateway</artifactId>
|
||||||
<packaging>pom</packaging>
|
<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>
|
<modules>
|
||||||
<module>image-microservice</module>
|
<module>image-microservice</module>
|
||||||
<module>price-microservice</module>
|
<module>price-microservice</module>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>api-gateway</artifactId>
|
<artifactId>api-gateway</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Async Method Invocation
|
title: Async Method Invocation
|
||||||
folder: async-method-invocation
|
folder: async-method-invocation
|
||||||
permalink: /patterns/async-method-invocation/
|
permalink: /patterns/async-method-invocation/
|
||||||
pumlid: TSdB3SCW303GLTe1mFTkunWhk0A3_4dKxTi5UdlIUuhIoCPfuz4Zjhy03EzwIlGyqjbeQR16fJL1HjuOQF362qjZbrFBnWWsTPZeFm3wHwbCZhvQ4RqMOSXIuA1_LzDctJd75m00
|
|
||||||
categories: Concurrency
|
categories: Concurrency
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>async-method-invocation</artifactId>
|
<artifactId>async-method-invocation</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -18,8 +18,8 @@ incomplete or inappropriate state
|
|||||||
## Applicability
|
## Applicability
|
||||||
Use the Balking pattern when
|
Use the Balking pattern when
|
||||||
|
|
||||||
*you want to invoke an action on an object only when it is in a particular state
|
* you want to invoke an action on an object only when it is in a particular state
|
||||||
*objects are generally only in a state that is prone to balking temporarily
|
* objects are generally only in a state that is prone to balking temporarily
|
||||||
but for an unknown amount of time
|
but for an unknown amount of time
|
||||||
|
|
||||||
## Related patterns
|
## Related patterns
|
||||||
|
@ -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>
|
<parent>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Bridge
|
title: Bridge
|
||||||
folder: bridge
|
folder: bridge
|
||||||
permalink: /patterns/bridge/
|
permalink: /patterns/bridge/
|
||||||
pumlid: BSR14SCm20J0Lf82BFxf1akCJ4R26ZZYzkE7zxLljJgoIVfu7S2A3v7pLRhYo3r3l9u6CPHwJjAH5uETllpZhKbejsqn86v1a-CExQwj2mdgqv8-oyev_W00
|
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>bridge</artifactId>
|
<artifactId>bridge</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -44,15 +44,15 @@ public abstract class WeaponTest {
|
|||||||
assertNotNull(weapon.getEnchantment());
|
assertNotNull(weapon.getEnchantment());
|
||||||
|
|
||||||
weapon.swing();
|
weapon.swing();
|
||||||
verify(enchantment, times(1)).apply();
|
verify(enchantment).apply();
|
||||||
verifyNoMoreInteractions(enchantment);
|
verifyNoMoreInteractions(enchantment);
|
||||||
|
|
||||||
weapon.wield();
|
weapon.wield();
|
||||||
verify(enchantment, times(1)).onActivate();
|
verify(enchantment).onActivate();
|
||||||
verifyNoMoreInteractions(enchantment);
|
verifyNoMoreInteractions(enchantment);
|
||||||
|
|
||||||
weapon.unwield();
|
weapon.unwield();
|
||||||
verify(enchantment, times(1)).onDeactivate();
|
verify(enchantment).onDeactivate();
|
||||||
verifyNoMoreInteractions(enchantment);
|
verifyNoMoreInteractions(enchantment);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Builder
|
title: Builder
|
||||||
folder: builder
|
folder: builder
|
||||||
permalink: /patterns/builder/
|
permalink: /patterns/builder/
|
||||||
pumlid: DSR94O0m2030LhG0mzzkC64KXs26GzlNZw_TcRLADagJwOWOlW8OFcNdE79B9wkN1ccKUdLWoGS33KwySMdalEioC89C7Jhw5zYIfNrIrFybhPUHNLu0
|
|
||||||
categories: Creational
|
categories: Creational
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>builder</artifactId>
|
<artifactId>builder</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Business Delegate
|
title: Business Delegate
|
||||||
folder: business-delegate
|
folder: business-delegate
|
||||||
permalink: /patterns/business-delegate/
|
permalink: /patterns/business-delegate/
|
||||||
pumlid: POl13SCm3CHMQGU8zUysgYCuBcJ5a4x9-l6_Fu84tzsgvYxf-Zg06HyYvxkqZYE_6UBrD8YXr7DGrxmPxFJZYxTTeZVR9WFY5ZGu5j2wkad4wYgD8IIe_xQaZp9pw0C0
|
|
||||||
categories: Business Tier
|
categories: Business Tier
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>business-delegate</artifactId>
|
<artifactId>business-delegate</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Caching
|
title: Caching
|
||||||
folder: caching
|
folder: caching
|
||||||
permalink: /patterns/caching/
|
permalink: /patterns/caching/
|
||||||
pumlid: DSRB4OKm2030LhG0m_rrWyWaE0bc-6ZxpujxsbMKUXwSrfSMCVq7OFYKAj5oJsUZIuCr2bq3fEU3WGOdthWTx59rcnZ1fWu3_GqGKXEjm47VIzeeCqV_0m00
|
|
||||||
categories: Other
|
categories: Other
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>caching</artifactId>
|
<artifactId>caching</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Callback
|
title: Callback
|
||||||
folder: callback
|
folder: callback
|
||||||
permalink: /patterns/callback/
|
permalink: /patterns/callback/
|
||||||
pumlid: FSVB4S8m30N0Lg20M7UwUL4qYOciUFGXxSE9s-wp6sjjKgwF8tF6YyXnjxtdKMk5E5-MOjdu6jIrRYIStlXWsIJwRij4fhW53SGFn51TmIT9yZ-jVBHPGxy0
|
|
||||||
categories: Other
|
categories: Other
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>callback</artifactId>
|
<artifactId>callback</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
127
chain/README.md
127
chain/README.md
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Chain of responsibility
|
title: Chain of responsibility
|
||||||
folder: chain
|
folder: chain
|
||||||
permalink: /patterns/chain/
|
permalink: /patterns/chain/
|
||||||
pumlid: 9SR13SCm20NGLTe1OkxTXX0KKzd4Wa-pVYlrdTxJN4OTMZ4U7LZv8Wg-ssdejLTgoELGHvDhaesw6HpqvWzlXwQTlYq6D3nfSlv2qjcS5F9VgvXjrHnV
|
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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
|
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.
|
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
|
## Applicability
|
||||||
Use Chain of Responsibility when
|
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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>chain</artifactId>
|
<artifactId>chain</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -85,9 +85,7 @@
|
|||||||
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
||||||
</module>
|
</module>
|
||||||
<module name="NeedBraces"/>
|
<module name="NeedBraces"/>
|
||||||
<module name="LeftCurly">
|
<module name="LeftCurly"/>
|
||||||
<property name="maxLineLength" value="120"/>
|
|
||||||
</module>
|
|
||||||
<module name="RightCurly"/>
|
<module name="RightCurly"/>
|
||||||
<module name="RightCurly">
|
<module name="RightCurly">
|
||||||
<property name="option" value="alone"/>
|
<property name="option" value="alone"/>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Command
|
title: Command
|
||||||
folder: command
|
folder: command
|
||||||
permalink: /patterns/command/
|
permalink: /patterns/command/
|
||||||
pumlid: DSgn4OCm30NGLM00h3xR25i7vYpXaxx2-g59zugtTgiZcwIFvGHcV8YSdt9qdBbdYDVR88PIRwK-yc6mqyLVtff4FsoR38XRa7Aye3SgMoD1_RkaQvcfumS0
|
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
@ -37,6 +36,10 @@ Use the Command pattern when you want to
|
|||||||
* implement callback functionality
|
* implement callback functionality
|
||||||
* implement the undo functionality
|
* implement the undo functionality
|
||||||
|
|
||||||
|
## Presentations
|
||||||
|
|
||||||
|
* [Command Pattern](etc/presentation.html)
|
||||||
|
|
||||||
## Real world examples
|
## Real world examples
|
||||||
|
|
||||||
* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
|
* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
|
||||||
|
@ -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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>command</artifactId>
|
<artifactId>command</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -29,7 +29,7 @@ package com.iluwatar.command;
|
|||||||
*/
|
*/
|
||||||
public enum Size {
|
public enum Size {
|
||||||
|
|
||||||
SMALL("small"), NORMAL("normal"), LARGE("large"), UNDEFINED("");
|
SMALL("small"), NORMAL("normal");
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ package com.iluwatar.command;
|
|||||||
*/
|
*/
|
||||||
public enum Visibility {
|
public enum Visibility {
|
||||||
|
|
||||||
VISIBLE("visible"), INVISIBLE("invisible"), UNDEFINED("");
|
VISIBLE("visible"), INVISIBLE("invisible");
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
|
@ -40,7 +40,9 @@ public class Wizard {
|
|||||||
private Deque<Command> undoStack = new LinkedList<>();
|
private Deque<Command> undoStack = new LinkedList<>();
|
||||||
private Deque<Command> redoStack = new LinkedList<>();
|
private Deque<Command> redoStack = new LinkedList<>();
|
||||||
|
|
||||||
public Wizard() {}
|
public Wizard() {
|
||||||
|
// comment to ignore sonar issue: LEVEL critical
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast spell
|
* Cast spell
|
||||||
|
@ -81,13 +81,13 @@ public class CommandTest {
|
|||||||
* @param goblin a goblin object whose state is to be verified against other parameters
|
* @param goblin a goblin object whose state is to be verified against other parameters
|
||||||
* @param expectedName expectedName of the goblin
|
* @param expectedName expectedName of the goblin
|
||||||
* @param expectedSize expected size 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,
|
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 name must be same as expectedName", expectedName, goblin.toString());
|
||||||
assertEquals("Goblin's size must be same as expectedSize", expectedSize, goblin.getSize());
|
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());
|
goblin.getVisibility());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Composite
|
title: Composite
|
||||||
folder: composite
|
folder: composite
|
||||||
permalink: /patterns/composite/
|
permalink: /patterns/composite/
|
||||||
pumlid: HSf13eCm30NHgy01YFUzZGaM62LEP7-NwvTTT_EaMTLgoqFIst81Cpv4payv5LVk6U9r6CHGwkYaBHy6EztyvUsGqDEsoO2u1NMED-WTvmY5aA3-LT9xcTdR3m00
|
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>composite</artifactId>
|
<artifactId>composite</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,7 @@ layout: pattern
|
|||||||
title: Converter
|
title: Converter
|
||||||
folder: converter
|
folder: converter
|
||||||
permalink: /patterns/converter/
|
permalink: /patterns/converter/
|
||||||
categories:
|
categories: Business Tier
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
- Difficulty-Beginner
|
- 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>
|
<parent>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -41,10 +41,7 @@ public class App {
|
|||||||
* @param args command line args
|
* @param args command line args
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Converter<UserDto, User> userConverter = new Converter<>(
|
Converter<UserDto, User> userConverter = new UserConverter();
|
||||||
userDto -> new User(userDto.getFirstName(), userDto.getLastName(), userDto.isActive(),
|
|
||||||
userDto.getEmail()),
|
|
||||||
user -> new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), user.getUserId()));
|
|
||||||
|
|
||||||
UserDto dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com");
|
UserDto dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com");
|
||||||
User user = userConverter.convertFromDto(dtoUser);
|
User user = userConverter.convertFromDto(dtoUser);
|
||||||
|
@ -68,7 +68,7 @@ public class Converter<T, U> {
|
|||||||
/**
|
/**
|
||||||
* @param dtoUsers collection of DTO entities
|
* @param dtoUsers collection of DTO entities
|
||||||
* @return List of domain representation of provided entities retrieved by
|
* @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) {
|
public final List<U> createFromDtos(final Collection<T> dtoUsers) {
|
||||||
return dtoUsers.stream().map(this::convertFromDto).collect(Collectors.toList());
|
return dtoUsers.stream().map(this::convertFromDto).collect(Collectors.toList());
|
||||||
@ -77,7 +77,7 @@ public class Converter<T, U> {
|
|||||||
/**
|
/**
|
||||||
* @param users collection of domain entities
|
* @param users collection of domain entities
|
||||||
* @return List of domain representation of provided entities retrieved by
|
* @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) {
|
public final List<T> createFromEntities(final Collection<U> users) {
|
||||||
return users.stream().map(this::convertFromEntity).collect(Collectors.toList());
|
return users.stream().map(this::convertFromEntity).collect(Collectors.toList());
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: CQRS
|
title: CQRS
|
||||||
folder: cqrs
|
folder: cqrs
|
||||||
permalink: /patterns/cqrs/
|
permalink: /patterns/cqrs/
|
||||||
pumlid: 7SPR4a0m3030gt00pR_RH6I8QQFouFgC_TfHb6gkd5Q7FQBx363ub4rYpoMTZKuDrYXqDX37HIuuyCPfPPTDfuuHREhGqBy0NUR0GNzAMYizMtq1
|
|
||||||
categories: Architectural
|
categories: Architectural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>cqrs</artifactId>
|
<artifactId>cqrs</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Data Access Object
|
title: Data Access Object
|
||||||
folder: dao
|
folder: dao
|
||||||
permalink: /patterns/dao/
|
permalink: /patterns/dao/
|
||||||
pumlid: 5SR14OKW30N0LhG0oVrt4o6ZE12Ov4NR_thQNQlc5aN2sd82qtz4naywAixOmyNoK8WYvT6fjdWOR7JnpLiHhuTkam4nTUhiRwZm847-J64zpUZj3m00
|
|
||||||
categories: Persistence Tier
|
categories: Persistence Tier
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>dao</artifactId>
|
<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 javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of {@link CustomerDao} that persists customers in RDBMS.
|
* An implementation of {@link CustomerDao} that persists customers in RDBMS.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DbCustomerDao implements CustomerDao {
|
public class DbCustomerDao implements CustomerDao {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(DbCustomerDao.class);
|
||||||
|
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,8 +69,8 @@ public class DbCustomerDao implements CustomerDao {
|
|||||||
Connection connection;
|
Connection connection;
|
||||||
try {
|
try {
|
||||||
connection = getConnection();
|
connection = getConnection();
|
||||||
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS"); //NOSONAR
|
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS"); // NOSONAR
|
||||||
ResultSet resultSet = statement.executeQuery(); //NOSONAR
|
ResultSet resultSet = statement.executeQuery(); // NOSONAR
|
||||||
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE,
|
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE,
|
||||||
Spliterator.ORDERED) {
|
Spliterator.ORDERED) {
|
||||||
|
|
||||||
@ -79,12 +83,12 @@ public class DbCustomerDao implements CustomerDao {
|
|||||||
action.accept(createCustomer(resultSet));
|
action.accept(createCustomer(resultSet));
|
||||||
return true;
|
return true;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e); // NOSONAR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, false).onClose(() -> mutedClose(connection, statement, resultSet));
|
}, false).onClose(() -> mutedClose(connection, statement, resultSet));
|
||||||
} catch (SQLException e) {
|
} 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();
|
statement.close();
|
||||||
connection.close();
|
connection.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
LOGGER.info("Exception thrown " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,19 +117,26 @@ public class DbCustomerDao implements CustomerDao {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Optional<Customer> getById(int id) throws Exception {
|
public Optional<Customer> getById(int id) throws Exception {
|
||||||
|
|
||||||
|
ResultSet resultSet = null;
|
||||||
|
|
||||||
try (Connection connection = getConnection();
|
try (Connection connection = getConnection();
|
||||||
PreparedStatement statement =
|
PreparedStatement statement =
|
||||||
connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
|
connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
|
||||||
|
|
||||||
statement.setInt(1, id);
|
statement.setInt(1, id);
|
||||||
ResultSet resultSet = statement.executeQuery();
|
resultSet = statement.executeQuery();
|
||||||
if (resultSet.next()) {
|
if (resultSet.next()) {
|
||||||
return Optional.of(createCustomer(resultSet));
|
return Optional.of(createCustomer(resultSet));
|
||||||
} else {
|
} else {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} 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();
|
statement.execute();
|
||||||
return true;
|
return true;
|
||||||
} catch (SQLException ex) {
|
} 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());
|
statement.setInt(3, customer.getId());
|
||||||
return statement.executeUpdate() > 0;
|
return statement.executeUpdate() > 0;
|
||||||
} catch (SQLException ex) {
|
} 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());
|
statement.setInt(1, customer.getId());
|
||||||
return statement.executeUpdate() > 0;
|
return statement.executeUpdate() > 0;
|
||||||
} catch (SQLException ex) {
|
} 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>data-bus</artifactId>
|
<artifactId>data-bus</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Data Mapper
|
title: Data Mapper
|
||||||
folder: data-mapper
|
folder: data-mapper
|
||||||
permalink: /patterns/data-mapper/
|
permalink: /patterns/data-mapper/
|
||||||
pumlid: JShB3OGm303HLg20nFVjnYGM1CN6ycTfVtFSsnjfzY5jPgUqkLqHwXy0mxUU8wuyqidQ8q4IjJqCO-QBWGOtVh5qyd5AKOmW4mT6Nu2-ZiAekapH_hkcSTNa-GC0
|
|
||||||
categories: Persistence Tier
|
categories: Persistence Tier
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>data-mapper</artifactId>
|
<artifactId>data-mapper</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Data Transfer Object
|
title: Data Transfer Object
|
||||||
folder: data-transfer-object
|
folder: data-transfer-object
|
||||||
permalink: /patterns/data-transfer-object/
|
permalink: /patterns/data-transfer-object/
|
||||||
pumlid: RSh14SCW30NHLk82GFTq8uDYum71I5zn-t41kUtCswrfwL4bhBzEOFcRoFZEHyCPUxXOcGfHv387jHutWuqk_dAguktGj1WGKwV1_WJLvqWmLl-8fRbVKa22yXTosCWhHly1
|
|
||||||
categories: Architectural
|
categories: Architectural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>data-transfer-object</artifactId>
|
<artifactId>data-transfer-object</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Decorator
|
title: Decorator
|
||||||
folder: decorator
|
folder: decorator
|
||||||
permalink: /patterns/decorator/
|
permalink: /patterns/decorator/
|
||||||
pumlid: HSV14SCm20J0Lk82BFxf1YF6LaP26ZZizfDVVhjRC-bPDRs_Bc35cyZvAMV3bKU6kao36ehCGQtdms2d3z-yLursshuOKBUWmV43LPNfZEcaaFzA-YWhH_y2
|
|
||||||
categories: Structural
|
categories: Structural
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
@ -35,7 +34,7 @@ Wikipedia says
|
|||||||
|
|
||||||
**Programmatic Example**
|
**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 {
|
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!
|
troll.fleeBattle(); // The troll shrieks in horror and runs away!
|
||||||
|
|
||||||
// change the behavior of the simple troll by adding a decorator
|
// change the behavior of the simple troll by adding a decorator
|
||||||
Troll clubbed = new ClubbedTroll(troll);
|
troll = new ClubbedTroll(troll);
|
||||||
clubbed.attack(); // The troll tries to grab you! The troll swings at you with a club!
|
troll.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.fleeBattle(); // The troll shrieks in horror and runs away!
|
||||||
```
|
```
|
||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>decorator</artifactId>
|
<artifactId>decorator</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -57,9 +57,9 @@ public class App {
|
|||||||
|
|
||||||
// change the behavior of the simple troll by adding a decorator
|
// change the behavior of the simple troll by adding a decorator
|
||||||
LOGGER.info("A troll with huge club surprises you.");
|
LOGGER.info("A troll with huge club surprises you.");
|
||||||
Troll clubbed = new ClubbedTroll(troll);
|
troll = new ClubbedTroll(troll);
|
||||||
clubbed.attack();
|
troll.attack();
|
||||||
clubbed.fleeBattle();
|
troll.fleeBattle();
|
||||||
LOGGER.info("Clubbed troll power {}.\n", clubbed.getAttackPower());
|
LOGGER.info("Clubbed troll power {}.\n", troll.getAttackPower());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Delegation
|
title: Delegation
|
||||||
folder: delegation
|
folder: delegation
|
||||||
permalink: /patterns/delegation/
|
permalink: /patterns/delegation/
|
||||||
pumlid: JSV14GCX20NGLf82LkxfXbN69OFeu2VRVdBCxRsdUhLiac6F2rZxHHHybwwuyimjKQT37ANEGMfvCpZepHy-ccpjVYm697pJuFq3DJ7f39rEWlhNaZ7Aoc5V
|
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Dependency Injection
|
title: Dependency Injection
|
||||||
folder: dependency-injection
|
folder: dependency-injection
|
||||||
permalink: /patterns/dependency-injection/
|
permalink: /patterns/dependency-injection/
|
||||||
pumlid: RSdB3SCW303GLPe1mFTkunWhSGG6-PEesxS3zFQajubIpyPf_NL6B7y363xra3XpJsUZgS4QbUO0wVbWeC65DvR6BeUMXH5iwZ3GVu36YxMnqgU8NamXKu63_aPD6tNbw5y0
|
|
||||||
categories: Behavioral
|
categories: Behavioral
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- 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>
|
<parent>
|
||||||
<groupId>com.iluwatar</groupId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
<version>1.17.0-SNAPSHOT</version>
|
<version>1.18.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>dependency-injection</artifactId>
|
<artifactId>dependency-injection</artifactId>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -3,7 +3,6 @@ layout: pattern
|
|||||||
title: Double Checked Locking
|
title: Double Checked Locking
|
||||||
folder: double-checked-locking
|
folder: double-checked-locking
|
||||||
permalink: /patterns/double-checked-locking/
|
permalink: /patterns/double-checked-locking/
|
||||||
pumlid: TSdH4SCW203GLTe1bFzkGv1J6qGFeLc_MI1_x-wzkv94uJ1vDVUrFm26LwxTMnonsMYgitgcEQ1BNEXeyCKVfiAxLqqBtTbqmy1z0ygCGpXHOpgv99bqTgt0JW-LmqPUCUGF
|
|
||||||
categories: Concurrency
|
categories: Concurrency
|
||||||
tags:
|
tags:
|
||||||
- Java
|
- Java
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user