CodeDifficulty: Intermediate3 min

Facade Template in Python, Java and TypeScript

Three subsystem classes and one facade method that calls them in order.

The Facade template is the pattern in its pure form, with the participant names from the class diagram. The facade's one method calls three subsystem classes and passes the first result to the second, an ordering the facade holds so that clients do not have to. The steps add each participant in Python, and the tabs give the complete program in three languages, each with its output.

Building the template one participant at a time

Subsystem classes

Ordinary classes with their own methods, unaware of any facade.

py
class SubsystemA:
    def prepare(self) -> str:
        return "A prepared"


class SubsystemB:
    def process(self, step: str) -> str:
        return f"B processed after {step}"

Facade

Holds the subsystem objects and calls them in order.

py
class Facade:
    def operation(self) -> list[str]:
        first = self._a.prepare()
        return [first, self._b.process(first), self._c.finish()]

Client

Calls the facade, and can still call a subsystem class.

py
client(Facade(SubsystemA(), SubsystemB(), SubsystemC()))
print(SubsystemC().finish(), "(called directly)")

The complete template

py
class SubsystemA:
    def prepare(self) -> str:
        return "A prepared"


class SubsystemB:
    def process(self, step: str) -> str:
        return f"B processed after {step}"


class SubsystemC:
    def finish(self) -> str:
        return "C finished"


class Facade:
    def __init__(self, a: SubsystemA, b: SubsystemB, c: SubsystemC) -> None:
        self._a = a
        self._b = b
        self._c = c

    def operation(self) -> list[str]:
        first = self._a.prepare()
        return [first, self._b.process(first), self._c.finish()]


def client(facade: Facade) -> None:
    for line in facade.operation():
        print(line)


client(Facade(SubsystemA(), SubsystemB(), SubsystemC()))
print(SubsystemC().finish(), "(called directly)")
OutputRan with python:3.12-slim (Python 3.12.13)
A prepared
B processed after A prepared
C finished
C finished (called directly)
The facade passes the first result on; the last line calls a subsystem class directly.
java
import java.util.List;

public class FaTemplate {
    static void client(Facade facade) {
        facade.operation().forEach(System.out::println);
    }

    public static void main(String[] args) {
        client(new Facade(new SubsystemA(), new SubsystemB(), new SubsystemC()));
        System.out.println(new SubsystemC().finish() + " (called directly)");
    }
}

class SubsystemA {
    String prepare() {
        return "A prepared";
    }
}

class SubsystemB {
    String process(String step) {
        return "B processed after " + step;
    }
}

class SubsystemC {
    String finish() {
        return "C finished";
    }
}

class Facade {
    private final SubsystemA a;
    private final SubsystemB b;
    private final SubsystemC c;

    Facade(SubsystemA a, SubsystemB b, SubsystemC c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    List<String> operation() {
        String first = a.prepare();
        return List.of(first, b.process(first), c.finish());
    }
}
OutputRan with eclipse-temurin:21-jdk (Java 21.0.12)
A prepared
B processed after A prepared
C finished
C finished (called directly)
Java places the client first so the source launcher finds `main`; the roles are the same.
ts
class SubsystemA {
  prepare(): string {
    return "A prepared";
  }
}

class SubsystemB {
  process(step: string): string {
    return `B processed after ${step}`;
  }
}

class SubsystemC {
  finish(): string {
    return "C finished";
  }
}

class Facade {
  constructor(
    private readonly a: SubsystemA,
    private readonly b: SubsystemB,
    private readonly c: SubsystemC,
  ) {}

  operation(): string[] {
    const first = this.a.prepare();
    return [first, this.b.process(first), this.c.finish()];
  }
}

function client(facade: Facade): void {
  facade.operation().forEach((line) => console.log(line));
}

client(new Facade(new SubsystemA(), new SubsystemB(), new SubsystemC()));
console.log(new SubsystemC().finish(), "(called directly)");
OutputRan with node:22-slim (Node 22.23.1), TypeScript 5.9.3
A prepared
B processed after A prepared
C finished
C finished (called directly)
Parameter properties hold the three subsystem objects.

The first three lines of output come from one facade call; the client never learned that B needs A's result. The fourth comes from SubsystemC used directly, which is allowed: the facade added a convenient path and closed none.