Wie der Adapter ist auch die Fassade (engl. Facade) einer Hüllenklasse. Während der Adapter hilft Methoden aus externen Komponenten aufzurufen und diese in das eigene System zu integrieren, ist es das Ziel der Fassade das eigene System nach außen so zu gestalten, dass es einfach durch externe Komponenten (= Clients) aufzurufen ist. Die Fassade gestaltet also die Schnittstelle über die Zugriffe von außen erfolgen. Es sollen i.d.R. nicht alle Methoden mit ihrer internen Signatur nach außen zur Verfügung gestellt werden. Die folgende Abbildung skizziert die Idee einer Fassade in einem UML-Komponentendiagramm.

Eine Fassade entkoppelt die Komponenten des entwickelten Systems von seinen Clients. Die Clients dürfen ausschließlich über die Fassade auf das System zugreifen. Hinter der Fassade gibt es mehrere Komponenten oder Subsysteme, die ihrerseits definierte Schnittstellen aufweisen und als Bausteine das System selbst verkörpern. Die Komponenten sind häufig viel komplexer, als es ein Client benötigt. Sie können in unterschiedlichen Programmiersprachen, mittels verschiedener Frameworks realisiert sein und in heterogenen Laufzeitumgebungen bereitgestellt werden (s. Kapitel Modularisierung und Architektur). Die Fassade greift ihrerseits auf diese Komponenten zu und verbirgt deren Komplexität vor den Clients. Eine Methode der Fassade kann z.B. eine logische Folge von internen Methodenaufrufen zu einer höherwertigen Funktionalität zusammenführen.

In der Praxis sind Fassaden-Klassen sehr häufig vorzufinden, da nahezu jedes System über die Jahre an Komplexität gewinnt und so irgendwann der Bedarf nach einer Fassade entsteht, um diese interne Komplexität überschaubar zu gestalten. Ein Softwaresystem entwickelt sich i.d.R. organisch weiter, dadurch dass verschiedene Entwickler an verschiedenen Stellen neue Klassen, Beziehungen und Methoden hinzufügen. Das System wird im Laufe seiner kontinuierlichen Weiterentwicklung sukzessive in Komponenten zerlegt, die von unterschiedlichen Teams betreut werden.

Fassaden können auch helfen, wenn später mehrere Komponenten wieder integriert werden sollen, weil sie fachlich ähnliche Funktionalitäten beinhalten. Die Fassade bietet dann eine einheitliche Schnittstelle über die Zugriffe von außen an die existierenden Komponenten delegiert werden können, während diese hinter der Fassade langsam verschmelzen.

Es gibt also zusammenfassend verschiedene Motive eine Fassade einzusetzen:

Das in der obigen Abbildung dargestellte UML-Komponentendiagramm soll anhand der mit Java 9 eingeführten Module (= Komponenten) folgend implementiert werden. Die Programmiersprache Java bietet seit ihrer Entstehung die Möglichkeit, die Sichtbarkeit von Klassen, ihren Attributen und Methoden, usw. einzuschränken. Per Default ist die Sichtbarkeit auf Inhalte innerhalb des eigenen Package beschränkt. Der Default kann über die bekannten Modifizierer public, private und protected angepasst werden. Seit Java 9 gibt es auf höherer Abstraktionsebene nun Module, die den Komponenten der Architektur entsprechen und über die ebenfalls die Sichtbarkeit gesteuert werden kann. Diese Module umfassen i.d.R. mehrere Packages und spezifizieren in ihrem Modul-Deskriptor (module-info.java) zum einen, von welchen anderen Modulen sie abhängig sind (requires <<module>>), und zum anderen, welche ihrer Packages sie an andere Module nach außen freigeben (exports <<package>>). Per Konvention werden die Module in Java genau wie Packages kleingeschrieben und mit einer umgekehrten Domain als identifizierendes Prefix bezeichnet. Auf das Domain-Prefix wird hier zur Vereinfachung verzichtet.

// module-info.java
module client {
    requires mySystem;
}

// Client.java
package client;
import facade.Facade;

public class Client {
    public static void main(String[] args) {
        System.out.println(Facade.helloFromX());
        System.out.println(Facade.welcomeHelloFromY());
        System.out.println(Facade.welcomeHelloFromXY());
    }
}
// module-info.java
module mySystem {
    requires componentX;
    requires componentY;
    exports facade;
}

// Facade.java
package facade;
import x.X2;
import y.Y1;

public class Facade {
    public static String helloFromX() { return X2.hello("X2"); }
    public static String welcomeHelloFromY() { return Y1.welcome() + Y1.hello(); }
    public static String welcomeHelloFromXY() { return Y1.welcome() + X2.hello("X2") + Y1.hello(); }
}
// module-info.java
module componentX {
    exports x to mySystem;
}

// X2.java
package x;

public class X2 extends X1 {
    public static String hello(String from) { return "Hello from " + from + ". "; }
    X3[] x3;
}
// module-info.java
module componentY {
    exports y to mySystem;
}

// Y1.java
package y;

public class Y1 {
    public static String welcome() { return "Welcome! "; }
    public static String hello() { return "Hello from " + Y1.class.getSimpleName() + ". "; }
}

Die gezeigten Code-Beispiele zum Entwurfsmuster Fassade finden sich im Verzeichnis /patterns/facade des Modul-Repository.