[
  {
    "path": ".github/workflows/maven.yml",
    "content": "on:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        java: [ 21 ]\n    name: Java ${{ matrix.java }}\n    steps:\n      - uses: actions/checkout@v2\n      - name: setup\n        uses: actions/setup-java@v1\n        with:\n          java-version: ${{ matrix.java }}\n      - name: build\n        run: |\n          mvn -B package\n"
  },
  {
    "path": ".gitignore",
    "content": "*.class\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n/classes/\n\ntarget/\n*.iml\n.idea/\n.classpath\n.project\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Rémi Forax\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# Design Patterns Reloaded\nImplementation of some design patterns in Java 21,\nsome of them are from the GoF, others are the one you usually see in programs.\n\nLike most of the GoF patterns, the implementations use delegation instead of inheritance,\nbut also emphasis immutability when necessary.\n\n- [abstract factory](src/main/java/abstractfactory) abstracts access to several factories\n- [adapter](src/main/java/adapter) to see an object from one interface as one from another interface\n- [builder](src/main/java/builder) constructs objects by name instead of by position\n- [chain of responsibility](src/main/java/chainofresponsibility) constructs a pipeline of objects that handle a request\n- [command](src/main/java/command), objects that are actions\n- [decorator](src/main/java/decorator) dynamically adds behavior to an existing object\n- [factory](src/main/java/factory) abstracts the creation of objects\n- [memoizer](src/main/java/memoizer) caches the result of a computation to avoid multiple re-computations of the same value\n- [monad](src/main/java/monad) wraps multiple disjoint states under a common API \n- [observer](src/main/java/observer) de-couples codes by pushing the values from an object to another one\n- proxy see [decorator](src/main/java/decorator)\n- singleton see [abstract-factory](src/main/java/abstractfactory)\n- [railwayswitch](src/main/java/railwayswitch) abstracts a cascade of if ... else\n- [state](src/main/java/state) delegates API implementation to an internal state object\n- [template_method](src/main/java/templatemethod) define a behavior with a generic part and a specific part \n- [typing](src/main/java/typing), 3 kinds of relations between a static type and a runtime class\n- [visitor / pattern matching](src/main/java/visitor), specify operations on a hierarchy of types outside that hierarchy\n\n\n## Old materials\n\nI've done a presentation in English at Devoxx 2015\n\nCorresponding [slides](https://speakerdeck.com/forax/design-pattern-reloaded-parisjug) used for\n[my presentation at ParisJUG in June 2015](http://www.parisjug.org/xwiki/wiki/oldversion/view/Meeting/20150602).\n\nNB: A port exists in [Scala](https://github.com/YannMoisan/design-pattern-reloaded)\n"
  },
  {
    "path": "pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n\n  <groupId>forax</groupId>\n  <artifactId>design-pattern-reloaded</artifactId>\n  <version>1.0-SNAPSHOT</version>\n\n  <properties>\n    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n    <maven.compiler.source>21</maven.compiler.source>\n    <maven.compiler.target>21</maven.compiler.target>\n  </properties>\n\n  <dependencies>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-api</artifactId>\n      <version>5.10.0</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <version>5.10.0</version>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n</project>\n"
  },
  {
    "path": "src/main/java/abstractfactory/README.md",
    "content": "# Abstract Factory\n\nLet's say we have a simple hierarchy of classes, with a `Bus` and a `Car` both implementing an interface `Vehicle`.\n\n```java\ninterface Vehicle { }\nrecord Bus(String color) implements Vehicle { }\nrecord Car() implements Vehicle { }\n```\n\n```mermaid\nclassDiagram\nclass Vehicle {\n  <<interface>>\n}\nclass Car {\n  <<record>>\n}\nclass Bus {\n  <<record>>\n  String color\n}\nVehicle <|.. Car\nVehicle <|.. Bus\n```\n\n## Static abstract factory\n\nAnd we want to create a `Vehicle` from a string, \"bus\" for a `Bus` and \"car\" for a `Car`,\none simple solution is to use a switch on the string\n\n```java\nsealed interface Vehicle permits Bus, Car {\n  static Vehicle create(String name) {\n    return switch(name) {\n      case \"bus\" -> new Bus(\"yellow\");\n      case \"car\" -> new Car();\n      default -> throw new IllegalArgumentException(\"unknown \" + name);\n    };\n  }\n}\nrecord Bus() implements Vehicle { }\nrecord Car() implements Vehicle { }\n```\n\nThe usage is the following\n```java\nVehicle vehicle = Vehicle.create(\"bus\");\nSystem.out.println(vehicle);  // it's a Bus\n```\n\nThe main issue of this design is that it only works with a closed hierarchy (the interface is declared `sealed`).\nA user of the interface `Vehicle` can not add a new subtype because all possible classes are handwritten\nin the `switch`.\n\nWe can also remark that passing parameters to the creation is not easy, here, we can only create a yellow bus. \n\nAn abstract factory abstracts over the concept of [factory](../factory) and\nallows creating instances of open hierarchy classes from parameters.\n\n\n## Dynamic abstract factory\n\nA dynamic abstract factory is an abstract factory (also called a **Registry**) that lets you register\n[factory](../factory) for a value (here a String) and then calls the factory for that value.\nIt uses a hashtable/dictionary (a `HashMap`) to associate the value to a factory (here a `Supplier`).\n\n```java\npublic class Registry {\n  private final HashMap<String, Supplier<? extends Vehicle>> map = new HashMap<>();\n    \n  public void register(String name, Supplier<? extends Vehicle> supplier) {\n    map.put(name, supplier);\n  }\n\n  public Vehicle create(String name) {\n    return map.computeIfAbsent(name, n -> { throw new IllegalArgumentException(\"Unknown \" + n); })\n        .get();\n  }\n}\n```\n\n```mermaid\nclassDiagram\nclass Registry {\n  register(String name, () -> Vehicle supplier)\n  create(String name) Vehicle\n}\nclass Vehicle {\n  <<interface>>\n}\nRegistry ..> Vehicle : creates\n```\n\nThe registry is first setup using the method `register` to add the association, then the method `create()`\ncan be called with a value.\n\n```java\nvar registry = new Registry();\nregistry.register(\"car\", Car::new);\nregistry.register(\"bus\", () -> new Bus(\"yellow\"));\n    \nvar vehicle = registry.create(\"bus\");\nSystem.out.println(vehicle1);  // it's a Bus\n```\n\nBecause the registry contains dynamic associations, a user that creates a new kind of `Vehicle`\ncan register it into the registry too.\n\nThis design is also flexible in terms of object creation, it's quite easy to register an instance\n(here `yellowBus`) to always be returned playing the same role as a\n[singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern)\nwithout the drawbacks of a singleton: you can test it, it's not a global property,\nits access is tied to the access or the registry.\n\n```java\nvar registry = new Registry();\n\n// as a singleton\nvar yellowBus = new Bus(\"yellow\");\nregistry.register(\"bus\", () -> yellowBus);\n```\n\nThis design is the basis of the [inversion of control](https://en.wikipedia.org/wiki/Inversion_of_control)\nand its most popular incarnation the [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection).\n\nThe registry can also be separated into two parts because all methods should be called first before calling\nthe method `create` using the [builder pattern](../builder), you can find an example of such transformation\nin the [command pattern](../command) repository.\n"
  },
  {
    "path": "src/main/java/abstractfactory/abstractfactory1.java",
    "content": "package abstractfactory;\n\npublic interface abstractfactory1 {\n  sealed interface Vehicle {\n    static Vehicle create(String name) {\n      return switch(name) {\n        case \"bus\" -> new Bus(\"yellow\");\n        case \"car\" -> new Car();\n        default -> throw new IllegalArgumentException(\"unknown \" + name);\n      };\n    }\n  }\n  record Bus(String color) implements Vehicle { }\n  record Car() implements Vehicle { }\n  \n  static void main(String[] args) {\n    var vehicle1 = Vehicle.create(\"bus\");\n    System.out.println(vehicle1);\n    var vehicle2 = Vehicle.create(\"car\");\n    System.out.println(vehicle2);\n  }\n}\n"
  },
  {
    "path": "src/main/java/abstractfactory/abstractfactory2.java",
    "content": "package abstractfactory;\n\nimport java.util.HashMap;\nimport java.util.function.Supplier;\n\npublic interface abstractfactory2 {\n  interface Vehicle { }\n  record Bus(String color) implements Vehicle { }\n  record Car() implements Vehicle { }\n  \n  class Registry {\n    private final HashMap<String, Supplier<? extends Vehicle>> map = new HashMap<>();\n    \n    public void register(String name, Supplier<? extends Vehicle> supplier) {\n      map.put(name, supplier);\n    }\n\n    public Vehicle create(String name) {\n      return map.computeIfAbsent(name, n -> { throw new IllegalArgumentException(\"Unknown \" + n); })\n          .get();\n    }\n  }\n  \n  static void main(String[] args) {\n    var registry = new Registry();\n    registry.register(\"car\", Car::new);\n\n    // as a singleton\n    var yellowBus = new Bus(\"yellow\");\n    registry.register(\"bus\", () -> yellowBus);\n    \n    var vehicle1 = registry.create(\"bus\");\n    System.out.println(vehicle1);\n    var vehicle2 = registry.create(\"car\");\n    System.out.println(vehicle2);\n  }\n}\n"
  },
  {
    "path": "src/main/java/adapter/README.md",
    "content": "# Adapter Pattern\n\nLet's say we have a simple interface like a `Logger`\n\n```java\ninterface Logger {\n  void log(String message);\n}\n```\n\nand we have an existing API that takes a `Logger`\n```java\npublic static void sayHello(Logger logger) {\n  logger.log(\"hello\");\n}\n```\n\nNow, we introduce another logging API named `Logger2`, perhaps from another library\n```java\nenum Level { WARNING, ERROR }\n\ninterface Logger2 {\n  void log(Level level, String message);\n}\n```\n\nand we want to use that new interface `Logger2` with the method `sayHello()`.\nObviously, we can not directly call `sayHello` with a `Logger2`, we need to do adaptation work.\n\n## Adapter when we do not control Logger2\n\nA `Logger2` is a Logger with a supplementary `Level` so adapting a `Logger2` to be a `Logger` necessitate a level.\n\n```java\npublic static Logger adapt(Logger2 logger2, Level level) {\n  return msg -> logger2.log(level, msg);\n}\n```\n\nAnd we can use the method `adapt()` like this\n```java\nLogger logger = adapt(logger2, Level.WARNING);\nlogger.log(\"abort abort !\");\n```\n\nAn adapter acts a vue that transfers the data from one method of the new interface\nto a method call to the old interface.\n\n## Adapter when we control Logger2\n\nIf we control `Logger2`, the method `adapt()` can be an instance method of `Logger2`\n```java\ninterface Logger2 {\n  void log(Level level, String message);\n\n  default Logger adapt(Level level) {\n    return msg -> log(level, msg);\n  }\n}\n```\n\nIn terms of UML diagram, the lambda inside adapt acts as an implementation of `Logger`\nthat delegates its implementation to `Logger2`\n\n```mermaid\nclassDiagram\nclass Logger {\n  <<interface>>\n  log(String message);\n}\nclass LoggerLambda {\n  <<lambda>>\n  log(String message);\n}\nclass Logger2 {\n  <<interface>>\n  log(Level level, String message)\n}\nLoggerLambda <|.. Logger\nLoggerLambda --> Logger2 : delegates\n```\n\nand we can call `adapt()` directly on an instance of `Logger2`\n```java\nLogger logger = logger2.adapt(Level.WARNING);\nlogger.log(\"abort abort !\");\n```\n"
  },
  {
    "path": "src/main/java/adapter/adapter1.java",
    "content": "package adapter;\n\npublic interface adapter1 {\n  interface Logger {\n    void log(String message);\n  }\n\n  static void sayHello(Logger logger) {\n    logger.log(\"hello\");\n  }\n\n  static void main(String[] args) {\n    Logger logger = System.out::println;\n  }\n}\n"
  },
  {
    "path": "src/main/java/adapter/adapter2.java",
    "content": "package adapter;\n\npublic interface adapter2 {\n  interface Logger {\n    void log(String message);\n  }\n  \n  enum Level { WARNING, ERROR }\n  interface Logger2 {\n    void log(Level level, String message);\n\n    default Logger adapt(Level level) {\n      return msg -> log(level, msg);\n    }\n  }\n\n  static Logger adapt(Logger2 logger2, Level level) {\n    return msg -> logger2.log(level, msg);\n  }\n\n  static void main(String[] args) {\n    Logger2 logger2 = (level, msg) -> System.out.println(level + \" \" + msg);\n    logger2.log(Level.ERROR, \"abort abort !\");\n\n    //Logger logger = adapt(logger2, Level.WARNING);\n    Logger logger = logger2.adapt(Level.WARNING);\n    logger.log(\"abort abort !\");\n  }\n}\n"
  },
  {
    "path": "src/main/java/builder/README.md",
    "content": "# Builder pattern\n\nBy default, when creating an instance, the arguments of the constructor are passed in order,\nthe association between an argument and a parameter depends on the position of the argument.\n\nFor example, if we define a `Spaceship`\n```java\nrecord Spaceship(String name, String captain, int torpedoes, int length) {}\n```\n\nan instance is created by calling the constructor\n```java\nvar spaceship = new Spaceship(\"foo\", 'baz', 3, 4);\n```\n\nThe problem is that it's hard to know when reading the last line, which component/property of the record\nis initialized with which value, apart from taking a look at the definition of the record which can be in another file.\n\nA builder improves the readability of the code by introducing method calls (that have a name)\nto initialize each component.\n```java\nvar spaceship = new SpaceshipBuilder()\n    .name(\"USS Enterprise\")\n    .captain(\"Kirk\")\n    .torpedoes(10_000)\n    .length(288_646)\n    .build()\n```\n\nA builder is a mutable class that allows to initialize an object by name.\nAll the intermediary methods return the builder itself (`this`) so the method calls can be chained. \n\n```mermaid\nclassDiagram\nclass Spaceship {\n  <<record>>\n  String name\n  String captain\n  int torpedoes\n  int length\n}\nclass SpaceshipBuilder {\n  name(String name) SpaceshipBuilder\n  captain(String captain) SpaceshipBuilder\n  torpedoes(int torpedoes) SpaceshipBuilder\n  length(int length) SpaceshipBuilder\n  Spaceship build()\n}\nSpaceshipBuilder ..> Spaceship : creates\n```\n\n```java\npublic class SpaceshipBuilder {\n  private String name;\n  private String captain;\n  private int torpedoes = -1;\n  private int length = -1;\n\n  public SpaceshipBuilder name(String name) {\n    this.name = name;\n    return this;\n  }\n  public SpaceshipBuilder captain(String captain) {\n    this.captain = captain;\n    return this;\n  }\n  public SpaceshipBuilder torpedoes(int torpedoes) {\n    this.torpedoes = torpedoes;\n    return this;\n  }\n  public SpaceshipBuilder length(int length) {\n    this.length = length;\n    return this;\n  }\n    \n  public Spaceship build() {\n    if (name == null || captain == null || torpedoes == -1 || length == -1) {\n      throw new IllegalStateException(\"name, captain, torpedoes or length not initialized\");\n    }\n    return new Spaceship(name, captain, torpedoes, length);\n  }\n}\n```\n\nThe main issue with this pattern is that it requires usually quite a lot of code and that IDEs do not track\nthe fact that if a component of the record is renamed, the method of the builder should be renamed too.\n\n\n## A generic builder\n\nUsing reflection, it is possible to implement a generic builder that avoids those pitfalls\nat the price of making the code slower\n\n```java\nvar spaceship = new Builder<>(MethodHandles.lookup(), Spaceship.class)\n    .with(Spaceship::name, \"USS Enterprise\")\n    .with(Spaceship::captain, \"Kirk\")\n    .with(Spaceship::torpedoes, 10_000)\n    .with(Spaceship::length, 288_646)\n    .build()\n```\n\nA simple implementation is available here [builder2.java](builder2.java).\n"
  },
  {
    "path": "src/main/java/builder/builder1.java",
    "content": "package builder;\n\npublic interface builder1 {\n  record Spaceship(String name, String captain, int torpedoes, int length) {}\n\n  class SpaceshipBuilder {\n    private String name;\n    private String captain;\n    private int torpedoes = -1;\n    private int length = -1;\n\n    public SpaceshipBuilder name(String name) {\n      this.name = name;\n      return this;\n    }\n    public SpaceshipBuilder captain(String captain) {\n      this.captain = captain;\n      return this;\n    }\n    public SpaceshipBuilder torpedoes(int torpedoes) {\n      this.torpedoes = torpedoes;\n      return this;\n    }\n    public SpaceshipBuilder length(int length) {\n      this.length = length;\n      return this;\n    }\n    \n    public Spaceship build() {\n      if (name == null || captain == null || torpedoes == -1 || length == -1) {\n        throw new IllegalStateException(\"name, captain, torpedoes or length not initialized\");\n      }\n      return new Spaceship(name, captain, torpedoes, length);\n    }\n  }\n\n  static void printSpaceship(Spaceship spaceship) {\n    System.out.println(spaceship);\n  }\n\n  static void main(String[] args) {\n    printSpaceship(\n        new SpaceshipBuilder()\n            .name(\"USS Enterprise\")\n            .captain(\"Kirk\")\n            .torpedoes(10_000)\n            .length(288_646)\n            .build());\n  }\n}\n"
  },
  {
    "path": "src/main/java/builder/builder2.java",
    "content": "package builder;\n\nimport java.io.Serializable;\nimport java.lang.invoke.MethodHandles;\nimport java.lang.invoke.MethodHandles.Lookup;\nimport java.lang.invoke.MethodType;\nimport java.lang.invoke.SerializedLambda;\nimport java.lang.reflect.RecordComponent;\nimport java.util.Arrays;\nimport java.util.Map;\n\nimport static java.lang.invoke.MethodType.methodType;\nimport static java.util.stream.Collectors.toMap;\nimport static java.util.stream.IntStream.range;\n\npublic interface builder2 {\n  class Builder<T extends Record> {\n    public interface Accessor<T, V> extends Serializable {\n      V apply(T t);\n    }\n\n    @SuppressWarnings(\"unchecked\")   // very wrong but works\n    private static <T extends Throwable> AssertionError rethrow(Throwable cause) throws T {\n      throw (T) cause;\n    }\n\n    private record HiddenClass(MethodType constructorType, Map<String, Integer> slotMap) { }\n\n    private static final ClassValue<HiddenClass> HIDDEN_CLASS_VALUE =\n        new ClassValue<>() {\n          @Override\n          protected HiddenClass computeValue(Class<?> type) {\n            var components = type.getRecordComponents();\n            var slotMap = range(0, components.length)\n                .boxed()\n                .collect(toMap(i -> components[i].getName(), i -> i));\n            var  constructorType= methodType(void.class,\n                Arrays.stream(components).map(RecordComponent::getType).toArray(Class[]::new));\n            return new HiddenClass(constructorType, slotMap);\n          }\n        };\n\n    private final Lookup lookup;\n    private final Class<T> type;\n    private final HiddenClass hiddenClass;\n    private final Object[] values;\n\n    public Builder(Lookup lookup, Class<T> type) {\n      this.lookup = lookup;\n      this.type = type;\n      var hiddenClass = HIDDEN_CLASS_VALUE.get(type);\n      this.hiddenClass = hiddenClass;\n      values = new Object[hiddenClass.slotMap.size()];\n    }\n\n    public <K> Builder<T> with(Accessor<? super T, ? extends K> accessor, K value) {\n      SerializedLambda lambda;\n      try {\n        var mh = lookup.findVirtual(accessor.getClass(), \"writeReplace\", methodType(Object.class));\n        lambda = (SerializedLambda) (Object) mh.invoke(accessor);\n      } catch(NoSuchMethodException | IllegalAccessException e) {\n        throw (LinkageError) new LinkageError().initCause(e);\n      } catch (Throwable e) {\n        throw rethrow(e);\n      }\n      var slot = hiddenClass.slotMap.get(lambda.getImplMethodName());\n      if (slot == null) {\n        throw new IllegalArgumentException(\"invalid method reference \" + accessor);\n      }\n      values[slot] = value;\n      return this;\n    }\n    \n    public T build() {\n      try {\n        var constructor = lookup.findConstructor(type, hiddenClass.constructorType);\n        return type.cast(constructor.invokeWithArguments(values));\n      } catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {\n        throw (LinkageError) new LinkageError().initCause(e);\n      } catch(Throwable e) {\n        throw rethrow(e);\n      }\n    }\n  }\n\n  // ---\n\n  record Spaceship(String name, String captain, int torpedoes, int length) {}\n\n  static void printSpaceship(Spaceship spaceship) {\n    System.out.println(spaceship);\n  }\n\n  static void main(String[] args) {\n    printSpaceship(\n        new Builder<>(MethodHandles.lookup(), Spaceship.class)\n            .with(Spaceship::name, \"USS Enterprise\")\n            .with(Spaceship::captain, \"Kirk\")\n            .with(Spaceship::torpedoes, 10_000)\n            .with(Spaceship::length, 288_646)\n            .build());\n  }\n}\n"
  },
  {
    "path": "src/main/java/chainofresponsibility/README.md",
    "content": "# Chain of Responsibility Pattern\n\nA chain of responsibility is a linked list of action that each take care of a part of a message/request.\n\nLet say we have a `Logger` with 3 `Level` of error message.\n```java\nenum Level {\n  INFO, WARNING, ERROR\n}\ninterface Logger {\n  void log(Level messageLevel, String message);\n}\n```\n\nNow, supose that we want to write a `Logger` that log the message on the console.\nThe idea of the chain of responsibility is not only do the work specific of the `Logger`\n(logging to the console) but also to delegate the work to the next `Logger` in the chain if it exists.\n```java\nrecord ConsoleLogger(Level level, Logger logger) implements Logger {\n  @Override\n  public void log(Level messageLevel, String message) {\n    if (messageLevel.compareTo(level) >= 0) {\n      System.out.println(\"log on console: \" + message);\n    }\n    if (logger != null) {\n      logger.log(messageLevel, message);\n    }\n  }\n}\n```\n\nUsing the same pattern, we can implement a `Logger` that log the error message on a file\n```java\nrecord FileLogger(Level level, Logger logger) implements Logger {\n  @Override\n  public void log(Level messageLevel, String message) {\n    if (messageLevel.compareTo(level) >= 0) {\n      System.out.println(\"log on file: \" + message);\n    }\n    if (logger != null) {\n      logger.log(messageLevel, message);\n    }\n  }\n}\n```\n\n```mermaid\nclassDiagram\nclass Logger {\n  <<interface>>\n  log(Level messageLevel, String message)\n}\nclass ConsoleLogger {\n  <<record>>\n  Level level\n  void log(Level messageLevel, String message)\n}\nclass FileLogger {\n  <<record>>\n  Level level\n  void log(Level messageLevel, String message)\n}\nConsoleLogger <|.. Logger\nFileLogger <|.. Logger\nConsoleLogger --> Logger : logger\nFileLogger --> Logger : logger\n```\n\nAnd use the different loggers by creating a linked list of loggers\n```java\nstatic void main(String[] args) {\n  var logger = new FileLogger(Level.WARNING, new ConsoleLogger(Level.INFO, null));\n  logger.log(Level.ERROR, \"database connection error\");\n  logger.log(Level.INFO, \"listen on port 7777\");\n}\n```\n\n\n\n## use delegation to share behavior\n\nWe can de-structure a bit the pattern by recognizing the checking the message level again the logger level\nand delegating to another logger operation can be written only once.\n\nIn that case, the console logger and the file logger are just lambdas\n```java\ninterface Logger {\n  void log(Level messageLevel, String message);\n\n  static Logger console() {\n    return (messageLevel, message) -> System.out.println(\"log on console: \" + message);\n  }\n\n  static Logger file() {\n    return (messageLevel, message) -> System.out.println(\"log on file: \" + message);\n  }\n  ...\n```\n\nand add a [decorator](../decorator) that filter the message depending on the message level\n\n```java\n  ...\n  default Logger withLevel(Level level) {\n    return (messageLevel, message) -> {\n      if (messageLevel.compareTo(level) >= 0) {\n        log(messageLevel, message);\n      }\n    };\n  }\n```\n\nand add another [decorator](../decorator) that delegate the logging of a message to another logger\n```java\n  \n  default Logger withLogger(Logger logger) {\n    return (messageLevel, message) -> {\n      log(messageLevel, message);\n      logger.log(messageLevel, message);\n    };\n  }\n}\n```\n\nNow creating the different logger is done by composing the different loggers \n```java\nstatic void main(String[] args) {\n  var logger = Logger.file().withLevel(Level.WARNING)\n      .withLogger(Logger.console().withLevel(Level.INFO));\n  logger.log(Level.ERROR, \"database connection error\");\n  logger.log(Level.INFO, \"listen on port 7777\");\n}\n```\n"
  },
  {
    "path": "src/main/java/chainofresponsibility/chainofresponsibility1.java",
    "content": "package chainofresponsibility;\n\npublic interface chainofresponsibility1 {\n  enum Level {\n    INFO, WARNING, ERROR\n  }\n  interface Logger {\n    void log(Level messageLevel, String message);\n  }\n\n  record ConsoleLogger(Level level, Logger logger) implements Logger {\n    @Override\n    public void log(Level messageLevel, String message) {\n      if (messageLevel.compareTo(level) >= 0) {\n        System.out.println(\"log on console: \" + message);\n      }\n      if (logger != null) {\n        logger.log(messageLevel, message);\n      }\n    }\n  }\n\n  record FileLogger(Level level, Logger logger) implements Logger {\n    @Override\n    public void log(Level messageLevel, String message) {\n      if (messageLevel.compareTo(level) >= 0) {\n        System.out.println(\"log on file: \" + message);\n      }\n      if (logger != null) {\n        logger.log(messageLevel, message);\n      }\n    }\n  }\n  \n  static void main(String[] args) {\n    var logger = new FileLogger(Level.WARNING, new ConsoleLogger(Level.INFO, null));\n    logger.log(Level.ERROR, \"database connection error\");\n    logger.log(Level.INFO, \"listen on port 7777\");\n  }\n}\n"
  },
  {
    "path": "src/main/java/chainofresponsibility/chainofresponsibility2.java",
    "content": "package chainofresponsibility;\n\npublic interface chainofresponsibility2 {\n  enum Level {\n    INFO, WARNING, ERROR\n  }\n  interface Logger {\n    void log(Level messageLevel, String message);\n\n    default Logger withLevel(Level level) {\n      return (messageLevel, message) -> {\n        if (messageLevel.compareTo(level) >= 0) {\n          log(messageLevel, message);\n        }\n      };\n    }\n\n    default Logger withLogger(Logger logger) {\n      return (messageLevel, message) -> {\n        log(messageLevel, message);\n        logger.log(messageLevel, message);\n      };\n    }\n\n    static Logger console() {\n      return (messageLevel, message) -> System.out.println(\"log on console: \" + message);\n    }\n\n    static Logger file() {\n      return (messageLevel, message) -> System.out.println(\"log on file: \" + message);\n    }\n  }\n  \n  static void main(String[] args) {\n    var logger = Logger.file().withLevel(Level.WARNING)\n        .withLogger(Logger.console().withLevel(Level.INFO));\n    logger.log(Level.ERROR, \"database connection error\");\n    logger.log(Level.INFO, \"listen on port 7777\");\n  }\n}\n"
  },
  {
    "path": "src/main/java/command/README.md",
    "content": "# Command Pattern\n\nA command pattern is the idea to consider an action as an object, so it can be as simple as\nusing a Runnable or a Consumer.\n\nLet's say we have a configuration with several options that can be activated or not\ndepending on the options on the command line, for example, if the option \"--long\" is present\non the command line, the field \"longForm\" of the configuration should be true.\n\n```java\nclass Config {\n  boolean showHidden = false;\n  boolean longForm = false;\n  boolean showInode = false;\n  boolean showHelp = false;\n\n  @Override\n  public String toString() {\n    return \"Config[showHidden: %s, longForm: %s, showInode: %s, showHelp: %s]\"\n        .formatted(showHidden, longForm, showInode, showHelp);\n  }\n}\n```\n\nIf we suppose that there is a method `config` that takes a list of arguments and returns a configuration  object,\nthe `main`should be something like this\n\n```java\nvar config = config(List.of(args));\nSystem.out.println(config);\nif (config.showHelp) {\n  System.out.println(\"\"\"\n      --all, -a: show hidden files\n      --long, -l: long form\n      --inode, -i: show inodes\n      --help, -h: show this help\n      \"\"\");\n}\n```\n\nA straw-man implementation of the method config can be this one\n```java\nstatic Config config(List<String> args) {\n  var config = new Config();\n  for(var arg: args) {\n    switch (arg) {\n      case \"-a\", \"--all\" -> {\n        if (config.showHidden) {\n          throw new IllegalStateException(\"--all specified twice\");\n        }\n        config.showHidden = true;\n      }\n      case \"-l\", \"--long\" -> {\n        if (config.longForm) {\n          throw new IllegalStateException(\"--long specified twice\");\n        }\n        config.longForm = true;\n      }\n      case \"-i\", \"--inode\" -> {\n        if (config.showInode) {\n          throw new IllegalStateException(\"--inode specified twice\");\n        }\n        config.showInode = true;\n      }\n      case \"-h\", \"--help\" -> {\n        if (config.showHelp) {\n          throw new IllegalStateException(\"--help specified twice\");\n        }\n        config.showHelp = true;\n      }\n      default -> {}  // ignore\n    }\n  }\n  return config;\n}\n```\n\nThis implementation is not clean, there is a lot of redundancy in the way having twice the same options\nis handled and if we want to add a new option we also to not forget to update the help description of the `main`.\n\n## Enter the command pattern\n\nThe idea is to see an action, here changing on field of the configuration from false to true\nas an object. Here, our record `Command` also store a `name` to be used to detect if several options\ncorrespond to the same command on the command line.\n\n```mermaid\nclassDiagram\nclass CommandRegistry {\n  registerOptions(List~String~ options, String description, Config -> void action)\n  command(String option) Command\n  help() String\n}\nclass Command {\n  <<record>>\n  String name\n  Config -> void action\n}\nCommandRegistry --> \"0..*\" Command\n```\n\nThe `CommandRegitry` store the association between an option as a String and the corresponding `Command`\nand also the help description.\n\n```java\nrecord Command(String name, Consumer<Config> action) {}\n\nclass CommandRegistry {\n  private final HashMap<String, Command> map = new HashMap<>();\n  private final StringBuilder help = new StringBuilder();\n\n  public void registerOptions(List<String> options, String description, Consumer<Config> action) {\n    var command = new Command(options.get(0), action);\n    options.forEach(option -> map.put(option, command));\n    help.append(String.join(\", \", options)).append(\": \").append(description).append(\"\\n\");\n  }\n\n  public Command command(String option) {\n    return map.get(option);\n  }\n\n  public String help() {\n    return help.toString();\n  }\n}\n```\n\nWe need a method to configure the `CommandRegistry` i.e. register all the commands with their options\n```java\nstatic CommandRegistry commandRegistry() {\n  var registry = new CommandRegistry();\n  registry.registerOptions(List.of(\"--all\", \"-a\"), \"show hidden files\", c -> c.showHidden = true);\n  registry.registerOptions(List.of(\"--long\", \"-l\"), \"long form\", c -> c.longForm = true);\n  registry.registerOptions(List.of(\"--inode\", \"-i\"), \"show inodes\", c -> c.showInode = true);\n  registry.registerOptions(List.of(\"--help\", \"-h\"), \"show this help\", c -> c.showHelp = true);\n  return registry;\n}\n```\n\nAnd we modify the `main` a little, to ask for the `CommmandRegistry` and pass it as parameter\nof the method `config`.\n```java\nvar registry = commandRegistry();\nvar config = config(registry, List.of(args));\nSystem.out.println(config);\nif (config.showHelp) {\n  System.out.println(registry.help());\n}\n```\n\nIn the method `config`, we loop over the argument, find the corresponding command (if it's an option)\nand call the `action` of the `Command` on the `Config` object. We also check that we don't see a command\nwith the same name twice.\n```java\nstatic Config config(CommandRegistry registry, List<String> args) {\n  var config = new Config();\n  var commandSet = new HashSet<String>();\n  for(var arg: args) {\n    var command = registry.command(arg);\n    if (command == null) {\n      continue;  // ignore\n    }\n    if (!commandSet.add(command.name)) {\n      throw new IllegalStateException(command.name + \" specified twice\");\n    }\n    command.action.accept(config);\n  }\n  return config;\n}\n```\n\nWe can change the code of the CommandRegistry a bit because we can recognize that the method `registerOptions`\nand the method `command` are not called at the same time, so separating them using\nthe [builder pattern](../builder) may make the code easier to use.\n\n\n## Using a builder\n\nThe idea is to have a builder to register all the options and to ask for the `CommandRegistry` once\nall the options with their corresponding command are registered.\n\nLet's refactor the code (change the code without changing the API) of `CommandRegistry`\n```java\nstatic CommandRegistry commandRegistry() {\n  return new CommandRegistry.Builder()\n      .registerOptions(List.of(\"--all\", \"-a\"), \"show hidden files\", c -> c.showHidden = true)\n      .registerOptions(List.of(\"--long\", \"-l\"), \"long form\", c -> c.longForm = true)\n      .registerOptions(List.of(\"--inode\", \"-i\"), \"show inodes\", c -> c.showInode = true)\n      .registerOptions(List.of(\"--help\", \"-h\"), \"show this help\", c -> c.showHelp = true)\n      .toRegistry();\n}\n```\n\nGiven that the `CommandRegitry` has no method `registerOptions` anymore, it's just something\nthat encapsulates the `Map` of `Command` and the help description.\nSo it can be modelled by a record like this:\n```java\nrecord CommandRegistry(Map<String, Command> commandMap, String help) {\n  public static class Builder {\n    private final HashMap<String, Command> map = new HashMap<>();\n    private final StringBuilder help = new StringBuilder();\n\n    public Builder registerOptions(List<String> options, String description, Consumer<Config> action) {\n      var command = new Command(options.get(0), action);\n      options.forEach(option -> map.put(option, command));\n      help.append(String.join(\", \", options)).append(\": \").append(description).append(\"\\n\");\n      return this;\n    }\n\n    public CommandRegistry toRegistry() {\n      return new CommandRegistry(Map.copyOf(map), help.toString());\n    }\n  }\n\n  public Command command(String option) {\n    return commandMap.get(option);\n  }\n}\n```\n\n```mermaid\nclassDiagram\nclass CommandRegistryBuilder {\n  registerOptions(List~String~ options, String description, Config -> void action)\n  toRegistry() CommandRegistry\n}\nclass CommandRegistry {\n  <<record>>\n  String help\n  command(String option) Command\n}\nclass Command {\n  <<record>>\n  String name\n  Config -> void action\n}\nCommandRegistryBuilder ..> CommandRegistry : creates\nCommandRegistry --> \"1..*\" Command\n```\n"
  },
  {
    "path": "src/main/java/command/command1.java",
    "content": "package command;\n\nimport java.util.List;\n\npublic interface command1 {\n  class Config {\n    boolean showHidden = false;\n    boolean longForm = false;\n    boolean showInode = false;\n    boolean showHelp = false;\n\n    @Override\n    public String toString() {\n      return \"Config[showHidden: %s, longForm: %s, showInode: %s, showHelp: %s]\"\n          .formatted(showHidden, longForm, showInode, showHelp);\n    }\n  }\n\n  static Config config(List<String> args) {\n    var config = new Config();\n    for(var arg: args) {\n      switch (arg) {\n        case \"-a\", \"--all\" -> {\n          if (config.showHidden) {\n            throw new IllegalStateException(\"--all specified twice\");\n          }\n          config.showHidden = true;\n        }\n        case \"-l\", \"--long\" -> {\n          if (config.longForm) {\n            throw new IllegalStateException(\"--long specified twice\");\n          }\n          config.longForm = true;\n        }\n        case \"-i\", \"--inode\" -> {\n          if (config.showInode) {\n            throw new IllegalStateException(\"--inode specified twice\");\n          }\n          config.showInode = true;\n        }\n        case \"-h\", \"--help\" -> {\n          if (config.showHelp) {\n            throw new IllegalStateException(\"--help specified twice\");\n          }\n          config.showHelp = true;\n        }\n        default -> {}  // ignore\n      }\n    }\n    return config;\n  }\n\n  static void main(String[] args){\n    args = new String[] { \"--all\", \"foo\", \"-i\", \"--help\" }; // DEBUG\n    var config = config(List.of(args));\n    System.out.println(config);\n    if (config.showHelp) {\n      System.out.println(\"\"\"\n          --all, -a: show hidden files\n          --long, -l: long form\n          --inode, -i: show inodes\n          --help, -h: show this help\n          \"\"\");\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/command/command2.java",
    "content": "package command;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.function.Consumer;\n\npublic interface command2 {\n  class Config {\n    boolean showHidden = false;\n    boolean longForm = false;\n    boolean showInode = false;\n    boolean showHelp = false;\n\n    @Override\n    public String toString() {\n      return \"Config[showHidden: %s, longForm: %s, showInode: %s, showHelp: %s]\"\n          .formatted(showHidden, longForm, showInode, showHelp);\n    }\n  }\n\n  record Command(String name, Consumer<Config> action) {}\n\n  class CommandRegistry {\n    private final HashMap<String, Command> map = new HashMap<>();\n    private final StringBuilder help = new StringBuilder();\n\n    public void registerOptions(List<String> options, String description, Consumer<Config> action) {\n      var command = new Command(options.get(0), action);\n      options.forEach(option -> map.put(option, command));\n      help.append(String.join(\", \", options)).append(\": \").append(description).append(\"\\n\");\n    }\n\n    public Command command(String option) {\n      return map.get(option);\n    }\n\n    public String help() {\n      return help.toString();\n    }\n  }\n\n  static Config config(CommandRegistry registry, List<String> args) {\n    var config = new Config();\n    var commandSet = new HashSet<String>();\n    for(var arg: args) {\n      var command = registry.command(arg);\n      if (command == null) {\n        continue;  // ignore\n      }\n      if (!commandSet.add(command.name)) {\n        throw new IllegalStateException(command.name + \" specified twice\");\n      }\n      command.action.accept(config);\n    }\n    return config;\n  }\n\n  static CommandRegistry commandRegistry() {\n    var registry = new CommandRegistry();\n    registry.registerOptions(List.of(\"--all\", \"-a\"), \"show hidden files\", c -> c.showHidden = true);\n    registry.registerOptions(List.of(\"--long\", \"-l\"), \"long form\", c -> c.longForm = true);\n    registry.registerOptions(List.of(\"--inode\", \"-i\"), \"show inodes\", c -> c.showInode = true);\n    registry.registerOptions(List.of(\"--help\", \"-h\"), \"show this help\", c -> c.showHelp = true);\n    return registry;\n  }\n\n  static void main(String[] args) {\n    args = new String[] { \"--all\", \"foo\", \"-i\", \"--help\" }; // DEBUG\n    var registry = commandRegistry();\n    var config = config(registry, List.of(args));\n    System.out.println(config);\n    if (config.showHelp) {\n      System.out.println(registry.help());\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/command/command3.java",
    "content": "package command;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Consumer;\n\npublic interface command3 {\n  class Config {\n    boolean showHidden = false;\n    boolean longForm = false;\n    boolean showInode = false;\n    boolean showHelp = false;\n\n    @Override\n    public String toString() {\n      return \"Config[showHidden: %s, longForm: %s, showInode: %s, showHelp: %s]\"\n          .formatted(showHidden, longForm, showInode, showHelp);\n    }\n  }\n\n  record Command(String name, Consumer<Config> action) {}\n\n  record CommandRegistry(Map<String, Command> commandMap, String help) {\n    public static class Builder {\n      private final HashMap<String, Command> map = new HashMap<>();\n      private final StringBuilder help = new StringBuilder();\n\n      public Builder registerOptions(List<String> options, String description, Consumer<Config> action) {\n        var command = new Command(options.get(0), action);\n        options.forEach(option -> map.put(option, command));\n        help.append(String.join(\", \", options)).append(\": \").append(description).append(\"\\n\");\n        return this;\n      }\n\n      public CommandRegistry toRegistry() {\n        return new CommandRegistry(Map.copyOf(map), help.toString());\n      }\n    }\n\n    public Command command(String option) {\n      return commandMap.get(option);\n    }\n  }\n\n  static Config config(CommandRegistry registry, List<String> args) {\n    var config = new Config();\n    var commandSet = new HashSet<String>();\n    for(var arg: args) {\n      var command = registry.command(arg);\n      if (command == null) {\n        continue;  // ignore\n      }\n      if (!commandSet.add(command.name)) {\n        throw new IllegalStateException(command.name + \" specified twice\");\n      }\n      command.action.accept(config);\n    }\n    return config;\n  }\n\n  static CommandRegistry commandRegistry() {\n    return new CommandRegistry.Builder()\n        .registerOptions(List.of(\"--all\", \"-a\"), \"show hidden files\", c -> c.showHidden = true)\n        .registerOptions(List.of(\"--long\", \"-l\"), \"long form\", c -> c.longForm = true)\n        .registerOptions(List.of(\"--inode\", \"-i\"), \"show inodes\", c -> c.showInode = true)\n        .registerOptions(List.of(\"--help\", \"-h\"), \"show this help\", c -> c.showHelp = true)\n        .toRegistry();\n  }\n\n  static void main(String[] args) {\n    args = new String[] { \"--all\", \"foo\", \"-i\", \"--help\" }; // DEBUG\n    var registry = commandRegistry();\n    var config = config(registry, List.of(args));\n    System.out.println(config);\n    if (config.showHelp) {\n      System.out.println(registry.help());\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/java/decorator/README.md",
    "content": "# The Decorator Pattern\n\nA decorator is a simple way  to a dynamically enhance and existing behavior using composition.\n\nLet say we have an interface `Coffee` that describe a Coffee by its cost and its ingredients \n\n```java\ninterface Coffee {\n  long cost();      // cost of the coffee, in cents\n  String ingredients();\n}\n```\n\nWe can write a simple implementation using a record.\n\n```mermaid\nclassDiagram\nclass Coffee {\n  <<interface>>\n  long cost()\n  String ingredients()\n}\nclass SimpleCoffee {\n  <<record>>\n  long cost\n  String ingredients()\n}\nCoffee <|.. SimpleCoffee\n```\n\n```java\nrecord SimpleCoffee(long cost) implements Coffee {\n  @Override\n  public String ingredients() {\n    return \"Coffee\";\n  }\n}\n```\n\nLet say we now want to represent a coffee with milk, this is a `Coffee` so it should implement the interface\n`Coffee`, it's cost is the cost of a simple coffee plus 50 cents and the ingredients is coffee and milk.\n\nBecause the behavior of a coffee with milk depends on the behavior of a coffee, a coffee with milk is created\nusing a coffee and delegates to that instance to get the cost of a coffee and the ingredient of a coffee.\n\n```java\nrecord WithMilk(Coffee coffee) implements Coffee {\n  @Override\n  public long cost() {\n    return coffee.cost() + 50;\n  }\n  \n  @Override\n  public String ingredients() {\n    return coffee.ingredients() + \", Milk\";\n  }\n}\n```\n\n```mermaid\nclassDiagram\nclass Coffee {\n  <<interface>>\n  long cost()\n  String ingredients()\n}\nclass SimpleCoffee {\n  <<record>>\n  long cost\n  String ingredients()\n}\nclass WithMilk {\n  <<record>>\n  long cost()\n  String ingredients()\n}\nCoffee <|.. SimpleCoffee\nCoffee <|.. WithMilk\nWithMilk --> \"1\" Coffee : coffee\n```\n\nSo `WithMilk` is simultaneously, a Coffee because it implements the interface `Coffee`and decorates an existing coffee\nby taking an instance of a Coffee as record component.\n\nIf we repeat the pattern with `WithSprinkles`.\n\n```java\nrecord WithSprinkles(Coffee coffee) implements Coffee { \n  @Override\n  public long cost() {\n    return coffee.cost() + 20;\n  }\n  \n  @Override\n  public String ingredients() {\n    return coffee.ingredients() + \", Sprinkles\";\n  }\n}\n```\n\nWe can see why this pattern is interesting because we have not only created a coffee with sprinkles but also\na coffee with milk and with sprinkles.\n\n```java\nCoffee coffee = new SimpleCoffee(100);\nCoffee coffeeWithMilk = new WithMilk(coffee);\nCoffee coffeeWithMilkAndSprinkles = new WithSprinkles(coffeeWithMilk);\nSystem.out.println(\"ingredients: \" + coffeeWithMilkAndSprinkles.ingredients());\nSystem.out.println(\"cost: \" + coffeeWithMilkAndSprinkles.cost() + \" cents\");\n```\n\nThis pattern is more powerful than the inheritance because it relies on the delegation which is a dynamic relation\nwhile the inheritance/extends is a static relation.\n\n\n## Improving the API if the hierarchy is sealed\n\nWe can improve the API if we do not allow users to define their own coffee,\nwe can sealed the interface and provide instance methods (`withMilk`` and `withSprinkles` here)\nto create a decorator from an existing instance more easily. \n\n```java\nsealed interface Coffee permits SimpleCoffee, WithMilk, WithSprinkles {\n  long cost();\n  String ingredients();\n\n  static Coffee simple(long cost) {\n    return new SimpleCoffee(cost);\n  }\n  default Coffee withMilk() {\n    return new WithMilk(this);\n  }\n  default Coffee withSprinkles() {\n    return new WithSprinkles(this);\n  }\n}\n```\n\nHere is the same example as above, written using the new API\n\n```java\nCoffee coffeeWithMilkAndSprinkles = Coffee.simple(100)\n    .withMilk()\n    .withSprinkles();\nSystem.out.println(\"ingredients: \" + coffeeWithMilkAndSprinkles.ingredients());\nSystem.out.println(\"cost: \" + coffeeWithMilkAndSprinkles.cost() + \" cents\");\n```\n\nApart from being easier in terms of method discovery, this API also does not explicitly reference the names\nof the implementations so `SimpleCoffee`, `WithMilk` and `WithSprinkles` can be hidden and non-public.\n\n\n## Relation with the Proxy Pattern\n\nA proxy is a decorator, so it implements an interface and delegate to an instance of that interface \nbut it has a different intent, the idea to intercept method calls to do cross-cutting operations\nlike logging, authentication, caching, etc.\n\nHere is an example of a proxy, a Coffee that logs its cost.\n\n```java\nrecord LoggingCoffee(Coffee coffee) {\n  @Override\n  public long cost() {\n    var cost = coffee.cost();\n    System.out.println(\"coffee cost \" + cost);  // simulate logging\n    return cost;\n  }\n\n  @Override\n  public String ingredients() {\n    return coffee.ingredients();\n  }\n}\n```\n\n"
  },
  {
    "path": "src/main/java/decorator/decorator1.java",
    "content": "package decorator;\n\npublic interface decorator1 {\n  interface Coffee {\n    long cost();\n    String ingredients();\n  }\n\n  record SimpleCoffee(long cost) implements Coffee {\n    @Override\n    public String ingredients() {\n      return \"Coffee\";\n    }\n  }\n\n  record WithMilk(Coffee coffee) implements Coffee {\n    @Override\n    public long cost() {\n      return coffee.cost() + 50;\n    }\n    @Override\n    public String ingredients() {\n      return coffee.ingredients() + \", Milk\";\n    }\n  }\n\n  record WithSprinkles(Coffee coffee) implements Coffee {\n    @Override\n    public long cost() {\n      return coffee.cost() + 20;\n    }\n    @Override\n    public String ingredients() {\n      return coffee.ingredients() + \", Sprinkles\";\n    }\n  }\n\n  static void main(String[] args){\n    Coffee coffee = new SimpleCoffee(100);\n    Coffee coffeeWithMilk = new WithMilk(coffee);\n    Coffee coffeeWithMilkAndSprinkles = new WithSprinkles(coffeeWithMilk);\n    System.out.println(\"ingredients: \" + coffeeWithMilkAndSprinkles.ingredients());\n    System.out.println(\"cost: \" + coffeeWithMilkAndSprinkles.cost() + \" cents\");\n  }\n}\n"
  },
  {
    "path": "src/main/java/decorator/decorator2.java",
    "content": "package decorator;\n\npublic interface decorator2 {\n  sealed interface Coffee {\n    long cost();\n    String ingredients();\n\n    static Coffee simple(long cost) {\n      return new SimpleCoffee(cost);\n    }\n    default Coffee withMilk() {\n      return new WithMilk(this);\n    }\n    default Coffee withSprinkles() {\n      return new WithSprinkles(this);\n    }\n  }\n\n  record SimpleCoffee(long cost) implements Coffee {\n    @Override\n    public String ingredients() {\n      return \"Coffee\";\n    }\n  }\n\n  record WithMilk(Coffee coffee) implements Coffee {\n    @Override\n    public long cost() {\n      return coffee.cost() + 50;\n    }\n    @Override\n    public String ingredients() {\n      return coffee.ingredients() + \", Milk\";\n    }\n  }\n\n  record WithSprinkles(Coffee coffee) implements Coffee {\n    @Override\n    public long cost() {\n      return coffee.cost() + 20;\n    }\n    @Override\n    public String ingredients() {\n      return coffee.ingredients() + \", Sprinkles\";\n    }\n  }\n\n  static void main(String[] args){\n    Coffee coffeeWithMilkAndSprinkles = Coffee.simple(100)\n            .withMilk()\n            .withSprinkles();\n    System.out.println(\"ingredients: \" + coffeeWithMilkAndSprinkles.ingredients());\n    System.out.println(\"cost: \" + coffeeWithMilkAndSprinkles.cost() + \" cents\");\n  }\n}\n"
  },
  {
    "path": "src/main/java/factory/README.md",
    "content": "# Factory\n\nA factory abstracts the creation of instances. Conceptually, it's a function that returns a different instances\neach time the function is called.\n\nLet's take an example, we have, at least, two kinds of `Vehicle` a `Car` and a `Bus` both takes a `Color` as parameter.\n\n```mermaid\nclassDiagram\nclass Vehicle {\n  <<interface>>\n}\nclass Car {\n  <<record>>\n}\nclass Bus {\n  <<record>>\n}\nclass Color {\n  <<enumeration>>\n  RED\n  BLUE\n}\nVehicle <|.. Car\nVehicle <|.. Bus\nCar --> \"1\" Color : color\nBus --> \"1\" Color : color\n```\n\n```java\nenum Color { RED, BLUE }\ninterface Vehicle { }\nrecord Car(Color color) implements Vehicle { }\nrecord Bus(Color color) implements Vehicle { }\n```\n\nA factory let you use the same code to create instances of the same kind+color.\nFor example, if we want to create 5 vehicles, with a method `create5()` like this.\n\n```java\nstatic List<Vehicle> create5(Supplier<Vehicle> factory) {\n  return Stream.generate(factory).limit(5).toList();\n}\n```\n\nA Supplier is a predefined function interfac of Java that takes nothing and return an object.\nWe can then create 5 red cars that way. \n\n```java\nSupplier<Vehicle> redCarFactory = () -> new Car(Color.RED);\nSystem.out.println(create5(redCarFactory));\n```\n\n## A factory with parameters\n\nA factory can also have parameters, in our example a color and we can specify that color\nto create a vehicle with the right color.\n\n```java\n@FunctionalInterface\ninterface VehicleFactory {\n  Vehicle create(Color color);\n\n  default Supplier<Vehicle> bind(Color color) {\n    return () -> create(color);\n  }\n}\n```\n\n```mermaid\nclassDiagram\nclass Vehicle {\n  <<interface>>\n}\nclass VehicleFactory {\n  <<interface>>\n  create(Color color) Vehicle\n}\nVehicleFactory ..> Vehicle : creates\n```\n\nBecause `VehicleFactory` is a functional interface, it can be initialized that way to create cars.\n```java\nVehicleFactory carFactory = Car::new;\n```\n\nWe can also [adapt](../adapter) the `VehicleFactory` to be seen as a supplier by providing the color.\n\n```java\nvar supplier = carFactory.bind(Color.RED);\nSystem.out.println(create5(supplier));\n```\n"
  },
  {
    "path": "src/main/java/factory/factory1.java",
    "content": "package factory;\n\nimport java.util.List;\nimport java.util.function.Supplier;\nimport java.util.stream.Stream;\n\npublic interface factory1 {\n  enum Color { RED, BLUE }\n  interface Vehicle { }\n  record Car(Color color) implements Vehicle { }\n  record Bus(Color color) implements Vehicle { }\n  \n  static List<Vehicle> create5(Supplier<Vehicle> factory) {\n    return Stream.generate(factory).limit(5).toList();\n  }\n  \n  static void main(String[] args) {\n    Supplier<Vehicle> redCarFactory = () -> new Car(Color.RED);\n    Supplier<Vehicle> blueBusFactory = () -> new Bus(Color.BLUE);\n    \n    System.out.println(create5(redCarFactory));\n    System.out.println(create5(blueBusFactory));\n  }\n}\n"
  },
  {
    "path": "src/main/java/factory/factory2.java",
    "content": "package factory;\n\nimport java.util.List;\nimport java.util.function.Supplier;\nimport java.util.stream.Stream;\n\npublic interface factory2 {\n  enum Color { RED, BLUE }\n  interface Vehicle { }\n  record Car(Color color) implements Vehicle { }\n  record Bus(Color color) implements Vehicle { }\n\n  @FunctionalInterface\n  interface VehicleFactory {\n    Vehicle create(Color color);\n\n    default Supplier<Vehicle> bind(Color color) {\n      return () -> create(color);\n    }\n  }\n\n  static List<Vehicle> create5(Supplier<Vehicle> factory) {\n    return Stream.generate(factory).limit(5).toList();\n  }\n  \n  static void main(String[] args) {\n    VehicleFactory carFactory = Car::new;\n    VehicleFactory busFactory = Bus::new;\n\n    System.out.println(create5(carFactory.bind(Color.RED)));\n    System.out.println(create5(busFactory.bind(Color.BLUE)));\n  }\n}\n"
  },
  {
    "path": "src/main/java/memoizer/README.md",
    "content": "# Memoizer Pattern\n\nThe result of pure function with one parameter, i.e. a function that has its return value only depending on the value\nof the parameter with no side effect, can be stored in a cache to avoid re-computation of this value.\n\nThe Memoizer Pattern provided a reusable class `Memoizer` allowing add a cache to the computation\nof a pure function.\n\n## The memoizer pattern using inheritance\n\nWe can use the [Template Method](../templatemethod) pattern and inheritance to create a class that let users\noverriding the method `compute()` while providing a method `memoize` that cache the result\nof a computation.\n\n```java\nabstract class Memoizer<V, R> {\n  private final HashMap<V, R> map = new HashMap<>();\n    \n  public final R memoize(V value) {\n    return map.computeIfAbsent(value, this::compute);\n  }\n    \n  protected abstract R compute(V value);\n}\n```\n\n```mermaid\nclassDiagram\nclass Memoizer~V,R~ {\n  <<abstract>>\n  memoize(V value) R\n  #compute(V value) R\n}\n```\n\nThis is how it can be used:\n```java\nvar memoizer = new Memoizer<Integer, Integer>() {\n  @Override\n  protected Integer compute(Integer n) {\n    if (n < 2) {\n      return 1;\n    }\n    return memoize(n - 1) + memoize(n - 2);\n  }\n};\n```\n\nBut as usual with inheritance, it's easy to mis-use that class because the API\ncontains both the méthod `compute()` and `memoize()` leading to two frequent mistake,\neither the computation in `compute` calling recursively the method `compute()` instead of\n`memoize()` or a user using the method `compute()` directly instead of the method `memoize()`.\nThis second mistake is less frequent because `compute` is declared protected an not public.\n\n\n## The Memoizer Pattern using delegation\n\nAs usual the solution is to avoid inheritance and use delegation instead. \n\nSo the class `Memoizer` can be written that way\n```java\nfinal class Memoizer<V, R> {\n  private final Function<? super V, ? extends R> function;\n  private final HashMap<V, R> map = new HashMap<>();\n    \n  public Memoizer(Function<? super V, ? extends R> function) {\n    this.function = function;\n  }\n\n  public R memoize(V value) {\n    return map.computeIfAbsent(value, function);\n  }\n}\n```\n\nbut in that case, the method `memoize()` is not available inside the lambda\n```java\nvar memoizer = new Memoizer<Integer, Integer>(n -> {\n      if (n < 2) {\n        return 1;\n      }\n      return memoize(n - 1) + memoize(n - 2);   //FIXME !!\n    });\n```\n\n\nTo solve that, we need to introduce a second parameter able to do recursive call, like this\n```java\nvar fibo = new Memoizer<Integer, Integer>((n, fib) -> {\n      if (n < 2) {\n        return 1;\n      }\n      return fib.apply(n - 1) + fib.apply(n - 2);\n    });\n```\n\nthis leads to the following code for the class `Memoizer`\n```java\nfinal class Memoizer<V, R> {\n  private final BiFunction<? super V, Function<? super V, ? extends R>, ? extends R> bifunction;\n  private final HashMap<V, R> map = new HashMap<>();\n    \n  public Memoizer(BiFunction<? super V, Function<? super V, ? extends R>, ? extends R> bifunction) {\n    this.bifunction = bifunction;\n  }\n\n  public R memoize(V value) {\n    return map.computeIfAbsent(value, v -> bifunction.apply(v, this::memoize));\n  }\n}\n```\n\n```mermaid\nclassDiagram\nclass Memoizer~V,R~ {\n  Memoizer((V, (V, R)) -> R biFunction)\n  memoize(V value) R\n}\n```\n\n"
  },
  {
    "path": "src/main/java/memoizer/memoizer1.java",
    "content": "package memoizer;\n\nimport static java.util.stream.IntStream.range;\n\nimport java.util.HashMap;\n\npublic interface memoizer1 {\n  abstract class Memoizer<V, R> {\n    private final HashMap<V, R> map = new HashMap<>();\n    \n    public final R memoize(V value) {\n      return map.computeIfAbsent(value, this::compute);\n    }\n    \n    protected abstract R compute(V value);\n  }\n  \n  static void main(String[] args) {\n    var memoizer = new Memoizer<Integer, Integer>() {\n      @Override\n      protected Integer compute(Integer n) {\n        if (n < 2) {\n          return 1;\n        }\n        return memoize(n - 1) + memoize(n - 2);\n      }\n    };\n    \n    range(0, 20).map(memoizer::memoize).forEach(System.out::println);\n  }\n}\n"
  },
  {
    "path": "src/main/java/memoizer/memoizer2.java",
    "content": "package memoizer;\n\nimport static java.util.stream.IntStream.range;\n\nimport java.util.HashMap;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\n\npublic interface memoizer2 {\n  final class Memoizer<V, R> {\n    private final BiFunction<? super V, Function<? super V, ? extends R>, ? extends R> bifunction;\n    private final HashMap<V, R> map = new HashMap<>();\n    \n    public Memoizer(BiFunction<? super V, Function<? super V, ? extends R>, ? extends R> bifunction) {\n      this.bifunction = bifunction;\n    }\n\n    public R memoize(V value) {\n      return map.computeIfAbsent(value, v -> bifunction.apply(v, this::memoize));\n    }\n  }\n  \n  static void main(String[] args) {\n    var fibo = new Memoizer<Integer, Integer>((n, fib) -> {\n      if (n < 2) {\n        return 1;\n      }\n      return fib.apply(n - 1) + fib.apply(n - 2);\n    });\n    \n    range(0, 20).map(fibo::memoize).forEach(System.out::println);\n  }\n}\n"
  },
  {
    "path": "src/main/java/monad/README.md",
    "content": "# Monad Pattern\n\nA monad is a class that encapsulates several disjoint states.\n\nLet say we have a `User` that comes from an untrusted source, by example, deserialized from a JSON request.\n```java\nrecord User(String name, int age) { }\n```\n\nWe want to validate that none of the values of that object is illegal,\na simple solution is to write a method `validateUser` like this\n```java\npublic static void validateUser(User user) {\n  if (user.name().isEmpty()) {\n    throw new IllegalArgumentException(\"name is empty\");\n  }\n  if (!(user.age() > 0 && user.age() < 150)) {\n    throw new IllegalArgumentException(\"age is not between 0 and 150\");\n  }\n}\n```\n\nThe problem with this solution is that if several values are illegal, only the first one is reported.\nA solution is to delay the report of the errors, gathering all of them and at the end report of all them.\nThis requires to have an object that can store the value to validate (here a user) and all the error at\nthe same time.\n\n## Enter the monad \n\n```java\nrecord Error(IllegalArgumentException e, Error next) { }\n\nrecord Validator<V>(V value, Error error) {\n  public Validator<V> check(Predicate<? super V> validation, String message) {\n    if (!validation.test(value)) {\n      return new Validator<>(value, new Error(new IllegalArgumentException(message), error));\n    }\n    return this;\n  }\n\n  public V orElseThrow() throws IllegalStateException {\n    if (error == null) {\n      return value;\n    }\n    var exception = new IllegalStateException();\n    Stream.iterate(error, Objects::nonNull, Error::next).map(Error::e).forEach(exception::addSuppressed);\n    throw exception;\n  }\n}\n```\n\nA monad stores both the value and an error (here a linked list of exceptions).\n\nIt has two kind of methods\n- intermediary operation, here `check(predicate, message)` that checks the value and return a new instance of monad\n  with the states updated\n- final operations that stop the processing, here `orElseThrow()` that returns the value or reports the exceptions.\n\n```mermaid\nclassDiagram\nclass Validator~V~ {\n  <<record>>\n  V value\n  Error error\n  check(Predicate~V~ validation, String message) Validator~V~\n  orElseThrow() V\n}\n```\n\nWith that `validateUser()` can be written that way\n```java\npublic static User validateUser(User user) {\n  return new Validator<>(user, null)\n      .check(u -> !u.name().isEmpty(), \"name is empty\")\n      .check(u -> u.age() >= 0 && u.age() <= 150, \"age is not between 0 and 150\")\n      .orElseThrow();\n}\n```\n\n## Improve the API by separating the accessor from the operation done on the accessor value\n\nWe can add an overloads to `check` that takes 2 parameters, a reference to an accessor method (like `User::name`) and\na predicate to cleanly express what test is done on what value.\n\n```java\nprivate static IntPredicate inBetween(int start, int end) {\n  return value -> value >= start && value <= end;\n}\n\npublic static User validateUser(User user) {\n  return new Validator<>(user, null)\n      .check(User::name, not(String::isEmpty), \"name is empty\")\n      .check(User::age,  inBetween(0, 150)::test, \"age is not between 0 and 150\")\n      .orElseThrow();\n}\n```\n\nIn that case, this method `check()` can be written using the function composition and delegate to\nthe method `check()` with one parameter.\n\n```java\nrecord Validator<V>(V value, Error error) {\n  ...\n  public <U> Validator<V> check(Function<? super V, ? extends U> projection, Predicate<? super U> validation, String message) {\n    return check(projection.andThen(validation::test)::apply, message);\n  }\n  ...\n}\n```\n\nThe JDK contains two monads\n[java.util.Optional](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html) and\n[java.util.stream.Stream](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/stream/Stream.html).\n"
  },
  {
    "path": "src/main/java/monad/monad1.java",
    "content": "package monad;\n\npublic interface monad1 {\n  record User(String name, int age) { }\n\n  static void validateUser(User user) {\n    if (user.name().isEmpty()) {\n      throw new IllegalArgumentException(\"name is empty\");\n    }\n    if (!(user.age() > 0 && user.age() < 150)) {\n      throw new IllegalArgumentException(\"age is not between 0 and 150\");\n    }\n  }\n\n  static void main(String[] args) {   // no monad\n    var user = new User(\"bob\", 12);\n    //var user = new User(\"\", -12);\n    validateUser(user);\n  }\n}\n"
  },
  {
    "path": "src/main/java/monad/monad2.java",
    "content": "package monad;\n\nimport monad.monad1.User;\n\nimport java.util.Objects;\nimport java.util.function.Predicate;\nimport java.util.stream.Stream;\n\npublic interface monad2 {\n  record User(String name, int age) { }\n\n  record Error(IllegalArgumentException e, Error next) { }\n\n  record Validator<V>(V value, Error error) {\n    public V orElseThrow() throws IllegalStateException {\n      if (error == null) {\n        return value;\n      }\n      var exception = new IllegalStateException();\n      Stream.iterate(error, Objects::nonNull, Error::next).map(Error::e).forEach(exception::addSuppressed);\n      throw exception;\n    }\n    \n    public Validator<V> check(Predicate<? super V> validation, String message) {\n      if (!validation.test(value)) {\n        return new Validator<>(value, new Error(new IllegalArgumentException(message), error));\n      }\n      return this;\n    }\n  }\n\n  static User validateUser(User user) {\n    return new Validator<>(user, null)\n        .check(u -> !u.name().isEmpty(), \"name is empty\")\n        .check(u -> u.age() >= 0 && u.age() <= 150, \"age is not between 0 and 150\")\n        .orElseThrow();\n  }\n\n  static void main(String[] args) {\n    var user = new User(\"bob\", 12);\n    //var user = new User(\"\", -12);\n    validateUser(user);\n  }\n}\n"
  },
  {
    "path": "src/main/java/monad/monad3.java",
    "content": "package monad;\n\nimport java.util.Objects;\nimport java.util.function.Function;\nimport java.util.function.IntPredicate;\nimport java.util.function.Predicate;\nimport java.util.stream.Stream;\n\nimport static java.util.function.Predicate.not;\n\npublic interface monad3 {\n  record User(String name, int age) { }\n\n  record Error(IllegalArgumentException e, Error next) { }\n\n  record Validator<V>(V value, Error error) {\n    public V orElseThrow() throws IllegalStateException {\n      if (error == null) {\n        return value;\n      }\n      var exception = new IllegalStateException();\n      Stream.iterate(error, Objects::nonNull, Error::next).map(Error::e).forEach(exception::addSuppressed);\n      throw exception;\n    }\n\n    public Validator<V> check(Predicate<? super V> validation, String message) {\n      if (!validation.test(value)) {\n        return new Validator<>(value, new Error(new IllegalArgumentException(message), error));\n      }\n      return this;\n    }\n\n    public <U> Validator<V> check(Function<? super V, ? extends U> projection, Predicate<? super U> validation, String message) {\n      return check(projection.andThen(validation::test)::apply, message);\n    }\n  }\n\n  static IntPredicate inBetween(int start, int end) {\n    return value -> value >= start && value <= end;\n  }\n\n  static User validateUser(User user) {\n    return new Validator<>(user, null)\n        .check(User::name, not(String::isEmpty), \"name is empty\")\n        .check(User::age,  inBetween(0, 150)::test, \"age is not between 0 and 150\")\n        .orElseThrow();\n  }\n\n  static void main(String[] args) {\n    var user = new User(\"bob\", 12);\n    //var user = new User(\"\", -12);\n    validateUser(user);\n  }\n}\n"
  },
  {
    "path": "src/main/java/observer/README.md",
    "content": "# Observer Pattern\n\nThe point of the observer pattern is to decouple two pieces of code by using an interface in the middle.\n\nLet say we want to model a `StockExchange` that have a balance and contains several quantities of stocks.\nFor example, here the balance is 5 000 and wa have 1 000 stocks of FOOGL and 2 000 stocks of PAPL.\n```java\n  static void main(String[] args) {\n    var stockExchange = new StockExchange();\n    stockExchange.setBalance(5_000);\n    stockExchange.setStockQuantity(\"FOOGL\", 1_000);\n    stockExchange.setStockQuantity(\"PAPL\", 2_000);\n    System.out.println(stockExchange);\n```\n\n```mermaid\nclassDiagram\nclass Order {\n  <<record>>\n  Kind kind\n  int quantity\n  String tick\n  int accountId\n}\nclass StockExchange {\n  setBalance(int balance)\n  setStockQuantity(String tick, int quantity)\n  process(List~Order~ orders) List~Order~\n}\nStockExchange ..> Order : process\n```\n\nAn exchange is able to process orders and group the rejected orders by `accountId`.\nAn order is rejected if the exchange has no enough stock to process a BUY order,\nhere the last BUY order can not be processed because the exchange has not 3 000 stocks of FOOGL.\n```java\n  record Order(Kind kind, int quantity, String tick, int accountId) {\n    enum Kind { BUY, SELL }\n  }\n\n  static void main(String[] args) {\n    ...\n    var orders = List.of(\n        new Order(Order.Kind.SELL, 200, \"FOOGL\", 12),\n        new Order(Order.Kind.BUY, 1_500, \"PAPL\", 12),\n        new Order(Order.Kind.BUY, 3_000, \"FOOGL\", 666)\n        );\n\n    var rejectedOrderList = stockExchange.process(orders);\n    var rejectedOrders = rejectedOrderList.stream()\n        .collect(Collectors.groupingBy(Order::accountId));\n```\n\nThis is the code of the `StockExchange`\n```java\n  class StockExchange {\n    private final TreeMap<String, Integer> stockMap = new TreeMap<>();\n    private int balance;\n\n    @Override\n    public String toString() {\n      return \"{stockMap: \" + stockMap + \", balance: \" + balance + \"}\";\n    }\n\n    public void setBalance(int balance) {\n      this.balance = balance;\n    }\n\n    public void setStockQuantity(String tick, int quantity) {\n      stockMap.put(tick, quantity);\n    }\n\n    public List<Order> process(List<? extends Order> orders) {\n      var rejectedOrders = new ArrayList<Order>();\n      for (var order : orders) {\n        switch (order.kind()) {\n          case BUY -> {\n            var stockQuantity = stockMap.getOrDefault(order.tick(), 0);\n            if (order.quantity() > stockQuantity) {\n              rejectedOrders.add(order);\n              continue;\n            }\n            stockMap.put(order.tick(), stockQuantity - order.quantity());\n            balance += order.quantity();\n          }\n          case SELL -> {\n            stockMap.merge(order.tick(), order.quantity(), Integer::sum);\n            balance -= order.quantity();\n          }\n        }\n      }\n      return rejectedOrders;\n    }\n  }\n```\n\n\nWe now want to add a code to log if the balance is less than 0 or more than 6 000, because\nhaving a negative balance is always bad and having too much money in a hot wallet is bad too.\n\nWe can patch the code of `process` to in case of a BUY check if the balance does not grow over 6 000\nor in case of a SELL if the balance does not go below 0, but it will make the code hard to maintain\nbecause we will be mixed the processing algorithm with other concerns.\nIt's better to decouple those thing by introducing an observer.\n\n## Enter the observer\n\nAn observer is an interface used to publish the state of an object so a code can react to it.\n\nIn our example, let's define a `BalanceObserver` that will be called each time the balance change\n```java\ninterface BalanceObserver {\n  void balanceChanged(int newValue);\n}\n```\n\n```mermaid\nclassDiagram\nclass BalanceObserver {\n  <<interface>>\n  balanceChanged(int newValue)\n}\nclass StockExchange {\n  StockExchange(BalanceObserver balanceObserver)\n  process(List~Order~ orders) List~Order~\n}\nStockExchange --> \"1\" BalanceObserver : balanceObserver\n```\n\nWe take the `BalanceObserver` at creation and called it each time the balance changed\n```java\nclass StockExchange {\n    private final BalanceObserver balanceObserver;\n    private final TreeMap<String, Integer> stockMap = new TreeMap<>();\n    private int balance;\n\n    public StockExchange(BalanceObserver balanceObserver) {\n      this.balanceObserver = balanceObserver;\n    }\n  ...\n\n    public List<Order> process(List<? extends Order> orders) {\n      var rejectedOrders = new ArrayList<Order>();\n      for (var order : orders) {\n        switch (order.kind()) {\n          case BUY -> {\n            var stockQuantity = stockMap.getOrDefault(order.tick(), 0);\n            if (order.quantity() > stockQuantity) {\n              rejectedOrders.add(order);\n              continue;\n            }\n            stockMap.put(order.tick(), stockQuantity - order.quantity());\n            balance += order.quantity();\n            balanceObserver.balanceChanged(balance);\n          }\n          case SELL -> {\n            stockMap.merge(order.tick(), order.quantity(), Integer::sum);\n            balance -= order.quantity();\n            balanceObserver.balanceChanged(balance);\n          }\n        }\n      }\n      return rejectedOrders;\n    }\n  }\n```\n\nWe can now implement the observer with the correct semantics\n```java\n    BalanceObserver balanceObserver = newValue -> {\n      if (newValue < 0) {\n        System.out.println(\"balance negative !!!\");\n        return;\n      }\n      if (newValue >= 6_000) {\n        System.out.println(\"balance too high !!!\");\n      }\n    };\n    var stockExchange = new StockExchange(balanceObserver);\n    ...\n```\n\nAs you can see, the code that reacts to the value of the balance being changed  is separated from\nthe code that process the orders thanks to the observer pattern.\n\nNote: historically, the observer pattern was called the observable/observer pattern and was able\nto have manage several observers instead of one like in the example above.\nWe now prefer to have only one observer and to use the design __pattern composite__ in case\nwe have several observers.\n\nHere is an example of such composite\n```java\n  record CompositeObserver(List<Observer> observers) implements Observer {\n    public void balanceChanged(int newValue) {\n      observers.forEach(observer -> observer.balanceChanged(value))\n    }\n  }\n```\n\n## More on observers\n\nIf we take a look to the initial code, there was already an observer hidden between the lines,\ninstead of using a list to collect the rejected orders, we should also apply the same\nprinciple and declare an observer of the rejected orders.\n\n```mermaid\nclassDiagram\nclass OrderObserver {\n  <<interface>>\n  rejected(Order order)\n}\nclass StockExchange {\n  process(List~Order~ orders, OrderObserver orderObserver) List~Order~\n}\nStockExchange ..> OrderObserver : uses\n```\n\n```java\ninterface OrderObserver {\n  void rejected(Order order);\n}\n\n...\n  public void process(List<? extends Order> orders, OrderObserver orderObserver) {\n    for (var order : orders) {\n      switch (order.kind()) {\n        case BUY -> {\n          var stockQuantity = stockMap.getOrDefault(order.tick(), 0);\n          if (order.quantity() > stockQuantity) {\n            orderObserver.rejected(order);\n            continue;\n          }\n          stockMap.put(order.tick(), stockQuantity - order.quantity());\n          balance += order.quantity();\n          balanceObserver.balanceChanged(balance);\n        }\n        case SELL -> {\n          stockMap.merge(order.tick(), order.quantity(), Integer::sum);\n          balance -= order.quantity();\n          balanceObserver.balanceChanged(balance);\n        }\n      }\n    }\n  }\n...\n```\n\nYou can note that this observer does not have to be stored in a field if it is only useful for a treatment.\n\nAnd in the `main()`, we can create the list that will store all rejected orders\n```java\n  ...\n  var rejectedOrderList = new ArrayList<Order>();\n  stockExchange.process(orders, rejectedOrderList::add);\n  var rejectedOrders = rejectedOrderList.stream()\n      .collect(Collectors.groupingBy(Order::accountId));\n  ...\n```\n\nor using a stream + mapMulti(), avoid the creation of the intermediary list\n```java\n  ...\n  var rejectedOrders = Stream.of(stockExchange)\n      .<Order>mapMulti((exchange, consumer) -> exchange.process(orders, consumer::accept))\n      .collect(Collectors.groupingBy(Order::accountId));\n  ...\n```\n\nThe Observer Pattern allow to decouple/untangle a code to create an on the shelf class that can be reused\nbecause it depends on an interface.\n\n"
  },
  {
    "path": "src/main/java/observer/observer1.java",
    "content": "package observer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.TreeMap;\nimport java.util.stream.Collectors;\n\npublic interface observer1 {\n  record Order(Kind kind, int quantity, String tick, int accountId) {\n    enum Kind { BUY, SELL }\n  }\n\n  class StockExchange {\n    private final TreeMap<String, Integer> stockMap = new TreeMap<>();\n    private int balance;\n\n    @Override\n    public String toString() {\n      return \"{stockMap: \" + stockMap + \", balance: \" + balance + \"}\";\n    }\n\n    public void setBalance(int balance) {\n      this.balance = balance;\n    }\n\n    public void setStockQuantity(String tick, int quantity) {\n      stockMap.put(tick, quantity);\n    }\n\n    public List<Order> process(List<? extends Order> orders) {\n      var rejectedOrders = new ArrayList<Order>();\n      for (var order : orders) {\n        switch (order.kind()) {\n          case BUY -> {\n            var stockQuantity = stockMap.getOrDefault(order.tick(), 0);\n            if (order.quantity() > stockQuantity) {\n              rejectedOrders.add(order);\n              continue;\n            }\n            stockMap.put(order.tick(), stockQuantity - order.quantity());\n            balance += order.quantity();\n          }\n          case SELL -> {\n            stockMap.merge(order.tick(), order.quantity(), Integer::sum);\n            balance -= order.quantity();\n          }\n        }\n      }\n      return rejectedOrders;\n    }\n  }\n\n  static void main(String[] args) {\n    var stockExchange = new StockExchange();\n    stockExchange.setBalance(5_000);\n    stockExchange.setStockQuantity(\"FOOGL\", 1_000);\n    stockExchange.setStockQuantity(\"PAPL\", 2_000);\n    System.out.println(stockExchange);\n\n    var orders = List.of(\n        new Order(Order.Kind.SELL, 200, \"FOOGL\", 12),\n        new Order(Order.Kind.BUY, 1_500, \"PAPL\", 12),\n        new Order(Order.Kind.BUY, 3_000, \"FOOGL\", 666)\n        );\n\n    var rejectedOrderList = stockExchange.process(orders);\n    var rejectedOrders = rejectedOrderList.stream()\n        .collect(Collectors.groupingBy(Order::accountId));\n\n    System.out.println(stockExchange);\n    System.out.println(\"rejected orders \" + rejectedOrders);\n  }\n}\n"
  },
  {
    "path": "src/main/java/observer/observer2.java",
    "content": "package observer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.TreeMap;\nimport java.util.stream.Collectors;\n\npublic interface observer2 {\n  record Order(Kind kind, int quantity, String tick, int accountId) {\n    enum Kind { BUY, SELL }\n  }\n\n  interface BalanceObserver {\n    void balanceChanged(int newValue);\n  }\n\n  class StockExchange {\n    private final BalanceObserver balanceObserver;\n    private final TreeMap<String, Integer> stockMap = new TreeMap<>();\n    private int balance;\n\n    public StockExchange(BalanceObserver balanceObserver) {\n      this.balanceObserver = balanceObserver;\n    }\n\n    @Override\n    public String toString() {\n      return \"{stockMap: \" + stockMap + \", balance: \" + balance + \"}\";\n    }\n\n    public void setBalance(int balance) {\n      this.balance = balance;\n    }\n\n    public void setStockQuantity(String tick, int quantity) {\n      stockMap.put(tick, quantity);\n    }\n\n    public List<Order> process(List<? extends Order> orders) {\n      var rejectedOrders = new ArrayList<Order>();\n      for (var order : orders) {\n        switch (order.kind()) {\n          case BUY -> {\n            var stockQuantity = stockMap.getOrDefault(order.tick(), 0);\n            if (order.quantity() > stockQuantity) {\n              rejectedOrders.add(order);\n              continue;\n            }\n            stockMap.put(order.tick(), stockQuantity - order.quantity());\n            balance += order.quantity();\n            balanceObserver.balanceChanged(balance);\n          }\n          case SELL -> {\n            stockMap.merge(order.tick(), order.quantity(), Integer::sum);\n            balance -= order.quantity();\n            balanceObserver.balanceChanged(balance);\n          }\n        }\n      }\n      return rejectedOrders;\n    }\n  }\n\n  static void main(String[] args) {\n    BalanceObserver balanceObserver = newValue -> {\n      if (newValue < 0) {\n        System.out.println(\"balance negative !!!\");\n        return;\n      }\n      if (newValue >= 6_000) {\n        System.out.println(\"balance too high !!!\");\n      }\n    };\n    var stockExchange = new StockExchange(balanceObserver);\n    stockExchange.setBalance(5_000);\n    stockExchange.setStockQuantity(\"FOOGL\", 1_000);\n    stockExchange.setStockQuantity(\"PAPL\", 2_000);\n    System.out.println(stockExchange);\n\n    var orders = List.of(\n        new Order(Order.Kind.SELL, 200, \"FOOGL\", 12),\n        new Order(Order.Kind.BUY, 1_500, \"PAPL\", 12),\n        new Order(Order.Kind.BUY, 3_000, \"FOOGL\", 666)\n        );\n\n    var rejectedOrderList = stockExchange.process(orders);\n    var rejectedOrders = rejectedOrderList.stream()\n        .collect(Collectors.groupingBy(Order::accountId));\n\n    System.out.println(stockExchange);\n    System.out.println(\"rejected orders \" + rejectedOrders);\n  }\n}\n"
  },
  {
    "path": "src/main/java/observer/observer3.java",
    "content": "package observer;\n\nimport java.util.List;\nimport java.util.TreeMap;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\npublic interface observer3 {\n  record Order(Kind kind, int quantity, String tick, int accountId) {\n    enum Kind { BUY, SELL }\n  }\n\n  interface BalanceObserver {\n    void balanceChanged(int newValue);\n  }\n\n  interface OrderObserver {\n    void rejected(Order order);\n  }\n\n  class StockExchange {\n    private final BalanceObserver balanceObserver;\n    private final TreeMap<String, Integer> stockMap = new TreeMap<>();\n    private int balance;\n\n    public StockExchange(BalanceObserver balanceObserver) {\n      this.balanceObserver = balanceObserver;\n    }\n\n    @Override\n    public String toString() {\n      return \"{stockMap: \" + stockMap + \", balance: \" + balance + \"}\";\n    }\n\n    public void setBalance(int balance) {\n      this.balance = balance;\n    }\n\n    public void setStockQuantity(String tick, int quantity) {\n      stockMap.put(tick, quantity);\n    }\n\n    public void process(List<? extends Order> orders, OrderObserver orderObserver) {\n      for (var order : orders) {\n        switch (order.kind()) {\n          case BUY -> {\n            var stockQuantity = stockMap.getOrDefault(order.tick(), 0);\n            if (order.quantity() > stockQuantity) {\n              orderObserver.rejected(order);\n              continue;\n            }\n            stockMap.put(order.tick(), stockQuantity - order.quantity());\n            balance += order.quantity();\n            balanceObserver.balanceChanged(balance);\n          }\n          case SELL -> {\n            stockMap.merge(order.tick(), order.quantity(), Integer::sum);\n            balance -= order.quantity();\n            balanceObserver.balanceChanged(balance);\n          }\n        }\n      }\n    }\n  }\n\n  static void main(String[] args) {\n    BalanceObserver balanceObserver = newValue -> {\n      if (newValue < 0) {\n        System.out.println(\"balance negative !!!\");\n        return;\n      }\n      if (newValue >= 6_000) {\n        System.out.println(\"balance too high !!!\");\n      }\n    };\n    var stockExchange = new StockExchange(balanceObserver);\n    stockExchange.setBalance(5_000);\n    stockExchange.setStockQuantity(\"FOOGL\", 1_000);\n    stockExchange.setStockQuantity(\"PAPL\", 2_000);\n    System.out.println(stockExchange);\n\n    var orders = List.of(\n        new Order(Order.Kind.SELL, 200, \"FOOGL\", 12),\n        new Order(Order.Kind.BUY, 1_500, \"PAPL\", 12),\n        new Order(Order.Kind.BUY, 3_000, \"FOOGL\", 666)\n        );\n    var rejectedOrders = Stream.of(stockExchange)\n        .<Order>mapMulti((exchange, consumer) -> exchange.process(orders, consumer::accept))\n        .collect(Collectors.groupingBy(Order::accountId));\n\n    System.out.println(stockExchange);\n    System.out.println(\"rejected orders \" + rejectedOrders);\n  }\n}\n"
  },
  {
    "path": "src/main/java/railwayswitch/README.md",
    "content": "# Railway Switch\n\nThe railway switch pattern, quoted by [Scott Wlaschin](https://fsharpforfunandprofit.com/rop/),\nis a way to abstract a cascade of **if ... else** to have a mode declarative way of specify\nhow a value can be obtained.\n\nFor example, we may want to determine the value of a hostname by either reading\nthe environment variable \"HOSTNAME\" or the Java property \"hostname\" or the property\n\"hostname\" of a configuration file or to use \"localhost\".\n\nThis can be written that way\n```java\npublic static String findHostname() {\n  // 1\n  var hostName = System.getenv(\"HOSTNAME\");\n  if (hostName != null) {\n    return hostName;\n  }\n\n  // 2\n  hostName = System.getProperty(\"hostname\");\n  if (hostName != null) {\n    return hostName;\n  }\n\n  // 3\n  var properties = new Properties();\n  try (var reader = Files.newBufferedReader(Path.of(\".config\"))) {\n    properties.load(reader);\n    hostName = properties.getProperty(\"hostname\");\n  } catch (IOException e) {\n    hostName = null;\n  }\n  if (hostName != null) {\n    return hostName;\n  }\n\n  // 4\n  return \"localhost\";\n}\n```\n\n## Railway switch pattern\n\nThe aim of the railway switch pattern is to simplify codes that do a cascade of **if ...  else**\nby creating higher level constructs (functions), here `environment()`, `systemProperty()`,\n`fileProperty()`, and a way to compose them (the function `or()`).\n\nFor our example, we want a code like this\n```java\n  static String findHostname() {\n    return environment(\"HOSTNAME\")\n        .or(systemProperty(\"hostname\"))\n        .or(fileProperty(Path.of(\".config\"), \"hostname\"))\n        .find()\n        .orElse(\"localhost\");\n  }\n```\n\nFor that, we first create a functional interface (`Finder`) that either return a value or no value\n(we use an `Optional` here) and an instance method `or` able to combine the result of two finders.\n\n```mermaid\nclassDiagram\nclass Finder {\n  <<interface>>\n  find() Optional~String~\n  or(Finder finder) Finder\n}\n```\n\n```java\n@FunctionalInterface\npublic interface Finder {\n  Optional<String> find();\n\n  default Finder or(Finder finder) {\n    return () -> find().or(finder::find);\n  }\n}\n```\n\nUsing a functional interface here allow to delay the computation in order to not do a side effect like reading\nthe configuration file if the value of the property have been found by one of the function before.\n\nOnce we have our interface `Finder` we can rewrite each code that try to find the value as\na method that returns a `Finder`.\n\n```java\nstatic Finder environment(String name) {\n  return () -> Optional.ofNullable(System.getenv(name));\n}\n\nstatic Finder systemProperty(String name) {\n  return () -> Optional.ofNullable(System.getProperty(name));\n}\n\nstatic Finder fileProperty(Path path, String name) {\n  return () -> {\n    var properties = new Properties();\n    try (var reader = Files.newBufferedReader(path)) {\n      properties.load(reader);\n      return Optional.ofNullable(properties.getProperty(name));\n    } catch (IOException e) {\n      return Optional.empty();\n    }\n  };\n}\n```\n\nThe railway switch pattern helps to move from a code describing how to reach an objective\nto a more declarative API separating how something can be found from how those things are combined.\n"
  },
  {
    "path": "src/main/java/railwayswitch/railwayswitch1.java",
    "content": "package railwayswitch;\n\nimport java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.Properties;\n\npublic interface railwayswitch1 {\n  static String findHostname() {\n    // 1\n    var hostName = System.getenv(\"HOSTNAME\");\n    if (hostName != null) {\n      return hostName;\n    }\n\n    // 2\n    hostName = System.getProperty(\"hostname\");\n    if (hostName != null) {\n      return hostName;\n    }\n\n    // 3\n    var properties = new Properties();\n    try (var reader = Files.newBufferedReader(Path.of(\".config\"))) {\n      properties.load(reader);\n      hostName = properties.getProperty(\"hostname\");\n    } catch (IOException e) {\n      hostName = null;\n    }\n    if (hostName != null) {\n      return hostName;\n    }\n\n    // 4\n    return \"localhost\";\n  }\n  \n  static void main(String[] args) {\n    var hostname = findHostname();\n    System.out.println(hostname);\n  }\n}\n"
  },
  {
    "path": "src/main/java/railwayswitch/railwayswitch2.java",
    "content": "package railwayswitch;\n\nimport java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.Optional;\nimport java.util.Properties;\n\npublic interface railwayswitch2 {\n  @FunctionalInterface\n  interface Finder {\n    Optional<String> find();\n\n    default Finder or(Finder finder) {\n      return () -> find().or(finder::find);\n    }\n  }\n\n  static Finder environment(String name) {\n    return () -> Optional.ofNullable(System.getenv(name));\n  }\n\n  static Finder systemProperty(String name) {\n    return () -> Optional.ofNullable(System.getProperty(name));\n  }\n\n  static Finder fileProperty(Path path, String name) {\n    return () -> {\n      var properties = new Properties();\n      try (var reader = Files.newBufferedReader(path)) {\n        properties.load(reader);\n        return Optional.ofNullable(properties.getProperty(name));\n      } catch (IOException e) {\n        return Optional.empty();\n      }\n    };\n  }\n\n  static String findHostname() {\n    return environment(\"HOSTNAME\")\n        .or(systemProperty(\"hostname\"))\n        .or(fileProperty(Path.of(\".config\"), \"hostname\"))\n        .find()\n        .orElse(\"localhost\");\n  }\n  \n  static void main(String[] args) {\n    var hostname = findHostname();\n    System.out.println(hostname);\n  }\n}\n"
  },
  {
    "path": "src/main/java/state/README.md",
    "content": "# The State Pattern\n\nWhen you have a workflow and you move from one state to another,\nit's often easier to read the code if each state is its own object.\n\nLet say there is a cart, I can add article to it, then I will pay for all the articles in it then\nI will ship the articles.\n\n```mermaid\nclassDiagram\nclass Article {\n  <<record>>\n  String name\n  long price\n}\nclass CreditCard {\n  <<record>>\n  String name\n  String id\n}\nclass Address {\n  <<record>>\n  String address\n  String country\n}\n```\n\nHere is an example of use (`info()` display the values of the state)\n```java\nvar cart = new Cart();\ncart.add(new Article(\"Lego Kit\", 9999));\nSystem.out.println(cart.info());\ncart.buy(new CreditCard(\"Mr Nobody\", \"1212_2121_1212_2121\"));\nSystem.out.println(cart.info());\ncart.ship(new Address(\"12 Nice Street, London\", \"England\"));\nSystem.out.println(cart.info());\n```\n\nRepresented as an automata, there are 3 states, `CREATED`, `PAYED`, `SHIPPED` and\n3 actions (transition) `add`, `buy` and `ship`.\n\n```mermaid\nflowchart LR\n  CREATED -- buy --> PAYED\n  PAYED -- ship --> SHIPPED\n  CREATED -- add --> CREATED\n```\n\n## An implementation with an enum\n\nOne naive implementation is to use an enum to represent the different states\n\n```mermaid\nclassDiagram\nclass State {\n <<enumeration>>\n CREATED\n PAYED\n SHIPPED\n}\nclass Cart {\n  add(Article article)\n  buy(CreditCard creditCard)\n  ship(Address address)\n  info() String\n}\nCart --> \"1\" State : state\nCart --> \"0..*\" Article : articles\nCart --> \"0..1\" Address : address\n```\n\n```java\nclass Cart {\n  private enum State { CREATED, PAYED, SHIPPED }\n\n  private List<Article> articles = new ArrayList<>();\n  private Address address;\n  private State state = State.CREATED;\n\n  public void add(Article article) {\n    if (state != State.CREATED) {\n      throw new IllegalStateException();\n    }\n    articles.add(article);\n  }\n\n  public void buy(CreditCard creditCard) {\n    if (state != State.CREATED) {\n      throw new IllegalStateException();\n    }\n    state = State.PAYED;\n    articles = List.copyOf(articles);\n  }\n\n  public void ship(Address address) {\n    if (state != State.PAYED) {\n      throw new IllegalStateException();\n    }\n    this.address = address;\n    state = State.SHIPPED;\n  }\n\n  public String info() {\n    return switch (state) {\n      case CREATED -> \"created articles \" + articles;\n      case PAYED -> \"payed articles \" + articles;\n      case SHIPPED -> \"shipped articles \" + articles + \" to \" + address;\n    };\n  }\n}\n```\n\nbut it is not clear which values (`articles` and `address`) is available at which state \nand it makes all values mutable.\n\n\n## An implementation with a hierarchy\n\nThe idea of the state pattern is that each state is represented by a different classes\nand all transitions are represented by pure functions, the mutable part is dealt in `Cart`\nby re-writing the field `state` so each implementation of the interface `State` can be immutable.\n\n```mermaid\nclassDiagram\nclass Cart {\n  add(Article article)\n  buy(CreditCard creditCard)\n  ship(Address address)\n  info() String\n}\nclass State {\n <<interface>>\n add(Article article)\n buy(CreditCard creditCard)\n ship(Address address)\n info() String\n}\nclass Created {\n  <<record>>\n}\nclass Payed {\n  <<record>>\n}\nclass Shipped {\n  <<record>>\n}\nCreated <|.. State\nPayed <|.. State\nShipped <|.. State\nCart --> \"1\" State : state\nCreated --> \"0..*\" Article : articles\nPayed --> \"0..*\" Article : articles\nShipped --> \"0..*\" Article : articles\nShipped --> \"0..1\" Address : address\n```\n\n```java\nclass Cart {\n  private sealed interface State {\n    State add(Article article);\n    State buy(CreditCard creditCard);\n    State ship(Address address);\n  }\n  private record Created(ArrayList<Article> articles) implements State { ... }\n  private record Payed(List<Article> articles) implements State { ... }\n  private record Shipped(List<Article> articles, Address address) implements State { ... }\n\n  private State state = new Created(new ArrayList<>());\n\n  public void add(Article article) {\n    state = state.add(article);\n  }\n  public void buy(CreditCard creditCard) {\n    state = state.buy(creditCard);\n  }\n  public void ship(Address address) {\n    state = state.ship(address);\n  }\n  public String info() {\n    return state.toString();\n  }\n}\n```\n\nInstead of having to implement all methods, in all subtypes of `State`,\nwe provide an implementation by default that throw an exception.\n\n```java\n  private sealed interface State {\n    default State add(Article article) {\n      throw new IllegalStateException();\n    }\n    default State buy(CreditCard creditCard) {\n      throw new IllegalStateException();\n    }\n    default State ship(Address address) {\n      throw new IllegalStateException();\n    }\n  }\n```\n\nThis is similar to adding a non-public abstract class in between the interface `State` and the implementations\nif the implementations are classes. Here, we use records that do not support inheritance.\n\nFor the state `Created`, we have a transition `add()` that cycle back to the same state (so it returns `this`)\nand a transition `buy()` that return a new state `Payed`. For `Payed`, we have a transition `ship()`\nthat returns a new state `Payed` which has no transition.\n\nYou can also remark that `Created` takes an `ArrayList` of articles because at that point it's a mutable structure\n(and the record is declared `private` so there is no problem to expose the implementation). `Payed` and\n`Shipped`, both takes an immutable list.\n\n```java\n  private record Created(ArrayList<Article> articles) implements State {\n    @Override\n    public State add(Article article) {\n      articles.add(article);\n      return this;\n    }\n\n    @Override\n    public State buy(CreditCard creditCard) {\n      return new Payed(List.copyOf(articles));\n    }\n  }\n  private record Payed(List<Article> articles) implements State {\n    @Override\n    public State ship(Address address) {\n      return new Shipped(articles, address);\n    }\n  }\n  private record Shipped(List<Article> articles, Address address) implements State { }\n```\n\nThe **State Pattern** splits the implementation on to each immutable state instead of having everything\nmutable in `Cart`.\n"
  },
  {
    "path": "src/main/java/state/state1.java",
    "content": "package state;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic interface state1 {\n  record Article(String name, long price) {}\n  record CreditCard(String name, String id) {}\n  record Address(String address, String country) {}\n\n  class Cart {\n    private enum State { CREATED, PAYED, SHIPPED }\n\n    private List<Article> articles = new ArrayList<>();\n    private Address address;\n    private State state = State.CREATED;\n\n    public void add(Article article) {\n      if (state != State.CREATED) {\n        throw new IllegalStateException();\n      }\n      articles.add(article);\n    }\n\n    public void buy(CreditCard creditCard) {\n      if (state != State.CREATED) {\n        throw new IllegalStateException();\n      }\n      state = State.PAYED;\n      articles = List.copyOf(articles);\n    }\n\n    public void ship(Address address) {\n      if (state != State.PAYED) {\n        throw new IllegalStateException();\n      }\n      this.address = address;\n      state = State.SHIPPED;\n    }\n\n    public String info() {\n      return switch (state) {\n        case CREATED -> \"created articles \" + articles;\n        case PAYED -> \"payed articles \" + articles;\n        case SHIPPED -> \"shipped articles \" + articles + \" to \" + address;\n      };\n    }\n  }\n\n  static void main(String[] args){\n    var cart = new Cart();\n    cart.add(new Article(\"Lego Kit\", 9999));\n    System.out.println(cart.info());\n    cart.buy(new CreditCard(\"Mr Nobody\", \"1212_2121_1212_2121\"));\n    System.out.println(cart.info());\n    cart.ship(new Address(\"12 Nice Street, London\", \"England\"));\n    System.out.println(cart.info());\n  }\n}\n"
  },
  {
    "path": "src/main/java/state/state2.java",
    "content": "package state;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic interface state2 {\n  record Article(String name, long price) {}\n  record CreditCard(String name, String id) {}\n  record Address(String address, String country) {}\n\n  class Cart {\n    private sealed interface State {\n      default State add(Article article) {\n        throw new IllegalStateException();\n      }\n      default State buy(CreditCard creditCard) {\n        throw new IllegalStateException();\n      }\n      default State ship(Address address) {\n        throw new IllegalStateException();\n      }\n    }\n    private record Created(ArrayList<Article> articles) implements State {\n      @Override\n      public State add(Article article) {\n        articles.add(article);\n        return this;\n      }\n\n      @Override\n      public State buy(CreditCard creditCard) {\n        return new Payed(List.copyOf(articles));\n      }\n    }\n    private record Payed(List<Article> articles) implements State {\n      @Override\n      public State ship(Address address) {\n        return new Shipped(articles, address);\n      }\n    }\n    private record Shipped(List<Article> articles, Address address) implements State { }\n\n    private State state = new Created(new ArrayList<>());\n\n    public void add(Article article) {\n      state = state.add(article);\n    }\n    public void buy(CreditCard creditCard) {\n      state = state.buy(creditCard);\n    }\n    public void ship(Address address) {\n      state = state.ship(address);\n    }\n    public String info() {\n      return state.toString();\n    }\n  }\n\n  static void main(String[] args){\n    var cart = new Cart();\n    cart.add(new Article(\"Lego Kit\", 9999));\n    System.out.println(cart.info());\n    cart.buy(new CreditCard(\"Mr Nobody\", \"1212_2121_1212_2121\"));\n    System.out.println(cart.info());\n    cart.ship(new Address(\"12 Nice Street, London\", \"England\"));\n    System.out.println(cart.info());\n  }\n}\n"
  },
  {
    "path": "src/main/java/templatemethod/README.md",
    "content": "# Template Method Pattern\n\nThe idea of the template method pattern is to decompose a problem in two parts, a generic reusable part\nand a specific part.\n\n## Using inheritance\n\nLet's say our generic part add hearts to a String and the specific part returns the string to be decorated. \n\nUsing an abstract class `DecoratedString, the abstract method `plainString()` returns the string to be decorated\nand the method `loveString()` the generic part that adds a heart before and after the string.\n```java\nabstract class DecoratedString {\n  protected abstract String plainString();\n\n  public String loveString() {\n    return \"❤️ \" + plainString() + \" ❤️\";\n  }\n}\n```\n\nand the specific part use inheritance (here with an anonymous class) to specify the string to be decorated.\n```java\nstatic void main(String[] args) {\n  var decoratedString = new DecoratedString() {\n    @Override\n    protected String plainString() {\n      return \"hello\";\n    }\n  };\n  System.out.println(decoratedString.loveString());\n}\n```\n\nUsing inheritance here as usual is not the best solution because the API of `DecoratedString` contains\nboth methods even if it may not make sense. In particular, inside the method `plainString()`,\none can call the method `loveString()` leading to a recursive loop that will blow the stack.\n\n\n## Using delegation\n\nA better design is to use delegation instead of inheritance.\nThe class `DecoratedString` takes a `Supplier` at construction and call it in `loveString()`.\n```java\nclass DecoratedString {\n  private final Supplier<String> supplier;\n\n  public DecoratedString(Supplier<String> supplier) {\n    this.supplier = supplier;\n  }\n\n  public String loveString() {\n    return \"❤️ \" + supplier.get() + \" ❤️\";\n  }\n}\n```\n\nA use site, the supplier can be specified as a lambda\n```java\nstatic void main(String[] args) {\n  var decoratedString = new DecoratedString(() -> \"hello\");\n  System.out.println(decoratedString.loveString());\n}\n```\n\nThe [Memoizer Pattern](../memoizer) is a more advanced example of template method pattern.\n\n\n"
  },
  {
    "path": "src/main/java/templatemethod/templatemethod1.java",
    "content": "package templatemethod;\n\npublic interface templatemethod1 {\n\n  abstract class DecoratedString {\n    protected abstract String plainString();\n\n    public String loveString() {\n      return \"❤️ \" + plainString() + \" ❤️\";\n    }\n  }\n\n  static void main(String[] args) {\n    var decoratedString = new DecoratedString() {\n      @Override\n      protected String plainString() {\n        return \"hello\";\n      }\n    };\n    System.out.println(decoratedString.loveString());\n  }\n}\n"
  },
  {
    "path": "src/main/java/templatemethod/templatemethod2.java",
    "content": "package templatemethod;\n\nimport java.util.function.Supplier;\nimport java.util.function.UnaryOperator;\n\npublic interface templatemethod2 {\n\n  class DecoratedString {\n    private final Supplier<String> supplier;\n\n    public DecoratedString(Supplier<String> supplier) {\n      this.supplier = supplier;\n    }\n\n    public String loveString() {\n      return \"❤️ \" + supplier.get() + \" ❤️\";\n    }\n  }\n\n  static void main(String[] args) {\n    var decoratedString = new DecoratedString(() -> \"hello\");\n    System.out.println(decoratedString.loveString());\n  }\n}\n"
  },
  {
    "path": "src/main/java/typing/dynamictyping.java",
    "content": "package typing;\n\npublic interface dynamictyping {\n  class A {\n    public void m() { \n      System.out.println(\"A::m\");\n    }\n  }\n  \n  class B {\n    public void m() { \n      System.out.println(\"B::m\");\n    }\n  }\n  \n  static void print(Object o) throws Exception {\n    o.getClass().getMethod(\"m\").invoke(o);\n  }\n  \n  public static void main(String[] args) throws Exception {\n    print(new A());\n    print(new B());\n  }\n}\n"
  },
  {
    "path": "src/main/java/typing/structuraltyping.java",
    "content": "package typing;\n\npublic interface structuraltyping {\n  interface I {\n    void m();\n  }\n  \n  class A {\n    public void m() { \n      System.out.println(\"A::m\");\n    }\n  }\n  \n  class B {\n    public void m() { \n      System.out.println(\"B::m\");\n    }\n  }\n  \n  static void print(I i) {\n    i.m();\n  }\n  \n  static void main(String[] args) {\n    print(new A()::m);\n    print(new B()::m);\n  }\n}\n"
  },
  {
    "path": "src/main/java/typing/subtyping.java",
    "content": "package typing;\n\npublic interface subtyping {\n  interface I {\n    void m();\n  }\n  \n  class A implements I {\n    public void m() { \n      System.out.println(\"A::m\");\n    }\n  }\n  \n  class B implements I {\n    public void m() { \n      System.out.println(\"B::m\");\n    }\n  }\n  \n  static void print(I i) {\n    i.m();\n  }\n  \n  static void main(String[] args) {\n    print(new A());\n    print(new B());\n  }\n}\n"
  },
  {
    "path": "src/main/java/visitor/README.md",
    "content": "# The Visitor Pattern\n\nThe aim of Visitor Pattern is to be able to specify operations on a hierarchy of classes outside that hierarchy.\n\n## Double dispatch\n\nLet say we have the following closed/sealed hierarchy\n```mermaid\nclassDiagram\nclass Vehicle {\n  <<interface>>\n}\nclass Car {\n <<record>>\n}\nclass CarHauler {\n  <<record>>\n}\nVehicle <|.. Car\nVehicle <|.. CarHauler\nCarHauler --> \"0..*\" Car : cars\n```\n\n```java\nsealed interface Vehicle permits Car, CarHauler { }\nrecord Car() implements Vehicle { }\nrecord CarHauler(List<Car> cars) implements Vehicle {}\n```\n\nand we want to specify operation outside that hierarchy.\nFor that we need an interface and a method per concrete classes.\n```java\ninterface Visitor<R> {\n  R visitCar(Car car);\n  R visitCarHauler(CarHauler carHauler);\n}\n```\n\nthen if we want by example count the number of cars, we can write the following visitor\n```java\nstatic int count(Vehicle vehicle) {\n  var visitor = new Visitor<Integer>() {\n    @Override \n    public Integer visitCar(Car car) {\n      return 1;\n    }\n      \n    @Override \n    public Integer visitCarHauler(CarHauler carHauler) {\n      return 1 + carHauler.cars().stream().mapToInt(car -> car.accept(this)).sum();\n    }\n  };\n  return vehicle.accept(visitor);\n}\n```\n\nYou can notice that we are using a mysterious method `accept()`. We can not directly call one of the methods\nvisit* of the interface `Visitor` with a `Vehicle` because we don't know witch one to call.\nThe method acts as a trampoline, when called on a vehicle with the visitor as parameter , it calls back\nthe right method of the `Visitor`.\n\nSo the hierarchy of vehicles needs to be modified to add the method `accept()`. \n\n```mermaid\nclassDiagram\nclass Visitor~R~ {\n  <<interface>>\n  visitCar(Car car) R\n  visitCarHauler(CarHauler carHauler) R\n}\nclass Vehicle {\n  <<interface>>\n  R accept(Visitor~R~ visitor)\n}\nclass Car {\n <<record>>\n R accept(Visitor~R~ visitor)\n}\nclass CarHauler {\n  <<record>>\n  R accept(Visitor~R~ visitor)\n}\nVehicle <|.. Car\nVehicle <|.. CarHauler\nCarHauler --> \"0..*\" Car : cars\nCar ..> Visitor: delegates\nCarHauler ..> Visitor: delegates\n```\n\n```java\nsealed interface Vehicle permits Car, CarHauler {\n  <R> R accept(Visitor<? extends R> visitor);\n}\nrecord Car() implements Vehicle {\n  @Override\n  public <R> R accept(Visitor<? extends R> visitor) {\n    return visitor.visitCar(this);\n  }\n}\nrecord CarHauler(List<Car> cars) implements Vehicle {\n  @Override\n  public <R> R accept(Visitor<? extends R> visitor) {\n    return visitor.visitCarHauler(this);\n  }\n}\n```\n\nThis technique to call the method `accept` that will then call the right method `visit*` of the Visitor\nis called the _double dispatch_ because effectively, there is one dynamic dispatch to call the right method accept\nfollowed by another dynamic dispatch call through the Visitor interface.\n\nThe drawback of this design is that it requires the hierarchy to be modified to add the method `accept`\nand only works on sealed hierarchy because you can not add new method in the `Visitor` interface.\n\nThe other issue is that because the visit is done outside the hierarchy, the class have to have accessor to\naccess the component values (the method `CarHauler.cars() in our example).\n\n\n## Dynamic visitor with an open hierarchy\n\nAnd what if we want the visitor to work on an open hierarchy ?\nIt means that we can not use an interface `Visitor` anymore, but you can replace it by as many functions\nas methods of the interface.\n\nIn that case, `Visitor` becomes a class with a method `when` that associate for a class the function to call\n(as a lambda) and a method `call` that for an instance of a `Vehicle` dynamically find its class and\ncalls the corresponding function.\n```mermaid\nclassDiagram\nclass Visitor~R~ {\n  when(Class~T~ type, T -> R fun) Visitor~R~\n  call(Object receiver) R\n}\n```\n\n```java\nstatic int count(Vehicle vehicle) {\n  var visitor = new Visitor<Integer>();\n  visitor.when(Car.class, car -> 1)\n         .when(CarHauler.class, carHauler -> 1 + carHauler.cars().stream().mapToInt(visitor::call).sum());\n  return visitor.call(vehicle);\n}\n```\n\nTo do the association between a class and the corresponding visiting function,  we use a hash table\n```java\npublic class Visitor<R> {\n  private final HashMap<Class<?>, Function<Object, ? extends R>> map = new HashMap<>();\n  \n  public <T> Visitor<R> when(Class<? extends T> type, Function<? super T, ? extends R> fun) {\n    map.put(type, fun.compose(type::cast));\n    return this;\n  }\n    \n  public R call(Object receiver) {\n    var receiverClass = receiver.getClass();\n    return map.computeIfAbsent(receiverClass, k -> { throw new IllegalArgumentException(\"invalid \" + k.getName()); })\n        .apply(receiver);\n  }\n}\n```\n\nYou can notice that in order to compile, we need to see a function that take a subtype of `Vehicle`as a funtion\nthat takes an `Object`. This is done by done a dynamic cast (the method reference `type::cast`).\n\n\n## Pattern matching\n\nThe visitor pattern is a way to a switch on a hierarchy of classes, starting with Java 21 we can now do a switch\non a sealed interface.\n\n```java\nstatic int count(Vehicle vehicle) {\n  return switch (vehicle) {\n    case Car car -> 1;\n    case CarHauler carHauler -> 1 + carHauler.cars().stream().mapToInt(car -> count(car)).sum();\n  };\n}\n```\n\nLike with the double dispatch, this requires the hierarchy to be sealed otherwise the compiler do not know\nif the cases cover all possible subtypes.\n\nJava also allow to match all the record components using a record pattern\n```java\nstatic int count(Vehicle vehicle) {\n  return switch (vehicle) {\n    case Car() -> 1;\n    case CarHauler(List<Car> cars) -> 1 + cars.stream().mapToInt(car -> count(car)).sum();\n  };\n}\n```\n\nIn the future, this capability will be extended to match not only records but also classes\n"
  },
  {
    "path": "src/main/java/visitor/visitor1.java",
    "content": "package visitor;\n\nimport java.util.List;\n\npublic interface visitor1 {\n  sealed interface Vehicle {\n    <R> R accept(Visitor<? extends R> visitor);\n  }\n  record Car() implements Vehicle {\n    @Override\n    public <R> R accept(Visitor<? extends R> visitor) {\n      return visitor.visitCar(this);\n    }\n  }\n  record CarHauler(List<Car> cars) implements Vehicle {\n    @Override\n    public <R> R accept(Visitor<? extends R> visitor) {\n      return visitor.visitCarHauler(this);\n    }\n  }\n  \n  interface Visitor<R> {\n    R visitCar(Car car);\n    R visitCarHauler(CarHauler carHauler);\n  }\n\n  static int count(Vehicle vehicle) {\n    var visitor = new Visitor<Integer>() {\n      @Override\n      public Integer visitCar(Car car) {\n        return 1;\n      }\n      @Override\n      public Integer visitCarHauler(CarHauler carHauler) {\n        return 1 + carHauler.cars().stream().mapToInt(car -> car.accept(this)).sum();\n      }\n    };\n    return vehicle.accept(visitor);\n  }\n\n  static void main(String[] args) {\n    var vehicle = new CarHauler(List.of(new Car(), new Car()));\n    var count = count(vehicle);\n    System.out.println(count);\n  }\n}\n"
  },
  {
    "path": "src/main/java/visitor/visitor2.java",
    "content": "package visitor;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.function.Function;\n\npublic interface visitor2 {\n  interface Vehicle { }\n  record Car() implements Vehicle { }\n  record CarHauler(List<Car> cars) implements Vehicle {}\n  \n  class Visitor<R> {\n    private final HashMap<Class<?>, Function<Object, ? extends R>> map = new HashMap<>();\n    \n    public <T> Visitor<R> when(Class<? extends T> type, Function<? super T, ? extends R> fun) {\n      map.put(type, fun.compose(type::cast));\n      return this;\n    }\n    public R call(Object receiver) {\n      var receiverClass = receiver.getClass();\n      return map.computeIfAbsent(receiverClass, k -> { throw new IllegalArgumentException(\"invalid \" + k.getName()); })\n          .apply(receiver);\n    }\n  }\n\n  static int count(Vehicle vehicle) {\n    var visitor = new Visitor<Integer>();\n    visitor.when(Car.class, car -> 1)\n        .when(CarHauler.class, carHauler -> 1 + carHauler.cars().stream().mapToInt(visitor::call).sum());\n    return visitor.call(vehicle);\n  }\n\n  static void main(String[] args) {\n    var vehicle = new CarHauler(List.of(new Car(), new Car()));\n    var count = count(vehicle);\n    System.out.println(count);\n  }\n}\n"
  },
  {
    "path": "src/main/java/visitor/visitor3.java",
    "content": "package visitor;\n\nimport java.util.List;\n\npublic interface visitor3 {\n  sealed interface Vehicle { }\n  record Car() implements Vehicle { }\n  record CarHauler(List<Car> cars) implements Vehicle {}\n\n  static int count(Vehicle vehicle) {\n    return switch (vehicle) {\n      case Car() -> 1;\n      case CarHauler(List<Car> cars) -> 1 + cars.stream().mapToInt(car -> count(car)).sum();\n    };\n  }\n\n  static void main(String[] args) {\n    var vehicle = new CarHauler(List.of(new Car(), new Car()));\n    var count = count(vehicle);\n    System.out.println(count);\n  }\n}\n"
  },
  {
    "path": "test/test.csv",
    "content": "1, 2, 4, 6.007\n4, 5, 6\n3\n"
  }
]