Practical Java15 sealed interfaces with design patterns
Tags: java, patterns, sealedclass, abstraction
Published: 2020-11-24 17:44:26

As a quick review of [template method](https://en.wikipedia.org/wiki/Template_method_pattern) and [chain of responsibility](https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern) patterns we can define a template of the chain (no to have a broken chain) with an abstract class:
```
abstract class MiddlewareBase {
    static MiddlewareBase of(MiddlewareBase... middlewares) {
        for (int i = 0; i < middlewares.length - 1; i++) {
            middlewares[i].setNext(middlewares[i + 1]);
        }
        return middlewares[0];
    }
    private MiddlewareBase next;
    public void setNext(MiddlewareBase next) {
        this.next = next;
    }
    public final void check(Request request) {
        checkInternal(request);
        if (next != null) {
            next.checkInternal(request);
        }
    }
    abstract void checkInternal(Request request);
}
```
Until now this is good and seems perfect, now to add more abstraction and to achieve the program to interface not implementation simple principle let us define the Middleware interface to represent our chain from interface perspective
```
interface Middleware {
    void check(Request request);
}
```
then we can re-write our MiddlewareBase as
```
abstract class MiddlewareBase implements Middleware {
    static Middleware of(MiddlewareBase... middlewares) {
        for (int i = 0; i < middlewares.length - 1; i++) {
            middlewares[i].setNext(middlewares[i + 1]);
        }
        return middlewares[0];
    }
    private MiddlewareBase next;
    public void setNext(MiddlewareBase next) {
        this.next = next;
    }
    public final void check(Request request) {
        checkInternal(request);
        if (next != null) {
            next.checkInternal(request);
        }
    }
    abstract void checkInternal(Request request);
}
```
with this and the two following simple examples of Middleware
```
class CsrfMiddleware extends MiddlewareBase {
    @Override
    void checkInternal(Request request) {
        System.out.println("csrf check");
    }
}
class XssMiddleware extends MiddlewareBase {
    @Override
    void checkInternal(Request request) {
        System.out.println("xss check");
    }
}
```
we can define and use our middleware chain like

```
Middleware middleware = MiddlewareBase.of(new CsrfMiddleware(), 
                                        new XssMiddleware());
middleware.check(new Request());
```
but nothing can prevent others from implementing the Middleware interface and break the chain implementation.
— — — — — —
Starting from version 15 and as a preview feature JDK presented the sealed class/interface feature to restrict which other classes or interfaces may extend or implement them.
we can define a sealed interface/class with `sealed` modifier, Then, after any `extends` and `implements` clauses, the `permits` clause specifies the classes that are permitted to extend the sealed class.
```
sealed interface Handler permits HandlerTemplate {
  void handle(Handleable handleable);
}
```
with this definition no class except `HandlerTemplate` can implement the `Handler` interface.
Let us now redefine the Middleware example with sealed interface so no one can implement it and break the main purpose of it as a CoR implementation.
```
sealed interface Middleware permits MiddlewareBase {
    void check(Request request);
}
```
The MiddlewareBase class will have no change except adding non-sealed modifier which means no restriction on implementation classes
```
abstract non-sealed class MiddlewareBase implements Middleware {
...
}
```
Also `CsrfMiddleware` and `XssMiddleware` will not change.
now if we tried to create another implementation of `Middleware` compiler will fail complaining: `class is not allowed to extend sealed class: Middleware` or with an IDE like intellij we get directly.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/qd9okwu816mrg27xyyky.png)

sealed classes/interfaces have many useful usecases and eventought it is new -still in preview- in Java it is presented in other languages like [Kotlin](https://kotlinlang.org/docs/reference/sealed-classes.html) (only sealed classes) and [Scala](https://docs.scala-lang.org/tour/traits.html) (sealed trait) with different intents.
I approached the sealed interfaces with core design principles and patterns to express the fact that the richer the language features the better design we get, comments are welcomed.