Commit 645a25f5 authored by Colin DAMON's avatar Colin DAMON

Merge branch '55-code-coffee-1' into 'master'

Resolve "Code & coffee 1"

Closes #55

See merge request !39
parents fa6ae32c 0e15b4a6
......@@ -16,3 +16,4 @@ include:
- local: "/trip-service-kata/.gitlab-ci.yml"
- local: "/tcr-roman-numerals/.gitlab-ci.yml"
- local: "/java-h2g2/.gitlab-ci.yml"
- local: "/factory-patterns/.gitlab-ci.yml"
......@@ -38,3 +38,4 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
| [Dev pour des data scientists, un sale boulot](https://www.youtube.com/watch?v=QK3OJGAresE) | Discussion | |
| [TCR - Roman Numerals](/tcr-roman-numerals) | Kata | Moyenne |
| [H2G2 en Java](/java-h2g2) | Kata | Moyenne |
| [Factory patterns](/factory-patterns) | Code&coffee | Facile |
package-factory-patterns:
variables:
PROJECT_FOLDER: "factory-patterns"
extends: .java
only:
refs:
- master
- merge_requests
changes:
- ".gitlab-common-ci.yml"
- "factory-patterns/**/*"
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<version>1.0.0</version>
<groupId>fr.ippon.kata</groupId>
<artifactId>java-parent</artifactId>
<relativePath>../java-parent</relativePath>
</parent>
<version>1.0.0-SNAPSHOT</version>
<artifactId>factory-patterns</artifactId>
<name>FactoryPatterns</name>
<developers>
<developer>
<email>arey@ippon.fr</email>
<name>Anthony REY</name>
</developer>
<developer>
<email>cdamon@ippon.fr</email>
<name>Colin DAMON</name>
</developer>
</developers>
</project>
# "factory" patterns
Live code & coffee. Sujet proposé par le chat : les patterns factory.
But de ces patterns : constuire des objets cohérents
## Static factory
Utilisation de méthodes statiques pour construire nos objets. Exemple dans `Firstname`.
Cas d'utilisation :
- Constuire un objet en ajoutant du sens grace au nom de la méthode ;
- Fermer l'extension (avec un constructeur privé) ;
- Permettre l'utilisation d'un cache ;
- Renvoyer un type différent (ex: Optional<T>).
## Builder
Objet mutable pour constuire des objets cohérents. Ils fournissent une API fluent (comme une phrase) pour construire sans ambiguité des objets complexes. Exemple dans `Person`.
## Factory method
On délégue une partie des responsabilité d'un objet à un tiers. Les enfants de notre objet doivent implémenter une méthode fournissant ce tiers. De cette manière on peut avoir une logique générale dans le parent et des spécificité dans chaque enfant.
## Abstract factory
Abstract factory permet de construire des objets abstraits en choisissant l'implémentation en fonction d'une clé. Dans ce cas on va créer une implémentation de factory par type d'objet a créer et utiliser cette implémentation pour construire nos objets en fonction de la clé.
package fr.ippon.factory;
import java.util.Optional;
public class Firstname {
private final String firstname;
public Firstname(String firstname) {
assertFirstname(firstname);
this.firstname = firstname;
}
private void assertFirstname(String firstname) {
if (firstname == null) {
throw new IllegalArgumentException();
}
}
public static Optional<Firstname> of(String firstname) {
if (firstname == null) {
return Optional.empty();
}
return Optional.of(new Firstname(firstname));
}
public String get() {
return firstname;
}
}
package fr.ippon.factory;
public class Lastname {
private final String lastname;
public Lastname(String lastname) {
assertLastname(lastname);
this.lastname = lastname;
}
private void assertLastname(String lastname) {
if (lastname == null) {
throw new IllegalArgumentException();
}
}
public String get() {
return lastname;
}
}
package fr.ippon.factory;
public class Person {
private final Firstname firstname;
private final Lastname lastname;
private Person(PersonBuilder builder) {
firstname = new Firstname(builder.firstname);
lastname = new Lastname(builder.lastname);
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public Firstname getFirstname() {
return firstname;
}
public Lastname getLastname() {
return lastname;
}
public static class PersonBuilder {
private String firstname;
private String lastname;
public PersonBuilder firstname(String firstname) {
this.firstname = firstname;
return this;
}
public PersonBuilder lastname(String lastname) {
this.lastname = lastname;
return this;
}
public Person build() {
return new Person(this);
}
}
}
package fr.ippon.factory;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class FirstnameTest {
@Test
void shouldNotBuildWithoutFirstname() {
assertThatThrownBy(() -> new Firstname(null)).isExactlyInstanceOf(IllegalArgumentException.class);
}
@Test
void shouldGetFirstname() {
assertThat(new Firstname("Jean").get()).isEqualTo("Jean");
}
@Test
void shouldGetEmptyFirstnameWithoutFirstname() {
assertThat(Firstname.of(null)).isEmpty();
}
@Test
void shouldGetFirstnameFromActualFirstname() {
assertThat(Firstname.of("Jean").get().get()).isEqualTo("Jean");
}
}
package fr.ippon.factory;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class LastnameTest {
@Test
void shouldNotBuildWithoutLastname() {
assertThatThrownBy(() -> new Lastname(null)).isExactlyInstanceOf(IllegalArgumentException.class);
}
@Test
void shouldGetLastname() {
assertThat(new Lastname("Dupont").get()).isEqualTo("Dupont");
}
}
package fr.ippon.factory;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class PersonTest {
@Test
void shouldGetPersonInformation() {
Person person = Person.builder().firstname("Jean").lastname("Dupont").build();
assertThat(person.getFirstname()).usingRecursiveComparison().isEqualTo(new Firstname("Jean"));
assertThat(person.getLastname()).usingRecursiveComparison().isEqualTo(new Lastname("Dupont"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment