StructuralTypeScriptverifiedVerified
Facade Pattern in TypeScript
Provides a simplified, unified interface to a complex subsystem, hiding its internal complexity from clients.
How to Implement the Facade Pattern in TypeScript
1Step 1: Define the complex subsystem classes
class SubsystemA {
operationA(): string { return "SubsystemA: ready"; }
operationA2(): string { return "SubsystemA: go!"; }
}
class SubsystemB {
operationB(): string { return "SubsystemB: ready"; }
operationB2(): string { return "SubsystemB: fire!"; }
}2Step 2: Create the Facade that orchestrates the subsystems
class Facade {
private a: SubsystemA;
private b: SubsystemB;
constructor(a?: SubsystemA, b?: SubsystemB) {
this.a = a ?? new SubsystemA();
this.b = b ?? new SubsystemB();
}
simpleOperation(): string {
const results = [
"Facade initialises subsystems:",
this.a.operationA(),
this.b.operationB(),
"Facade triggers subsystems:",
this.a.operationA2(),
this.b.operationB2(),
];
return results.join("\n");
}
}3Step 3: Use the simplified Facade interface
function clientCode(facade: Facade): void {
console.log(facade.simpleOperation());
}
clientCode(new Facade());// Facade Pattern – Production
// Single convert() call hides codec detection, transcoding,
// thumbnail extraction, and metadata writing.
// ── Subsystems (stubs simulating real libraries) ───────────────────────────────
class CodecDetector {
detect(filePath: string): string {
const ext = filePath.split(".").pop() ?? "";
const map: Record<string, string> = { mp4: "h264", mkv: "h265", avi: "xvid" };
return map[ext] ?? "unknown";
}
}
class VideoTranscoder {
transcode(input: string, output: string, codec: string): void {
console.log(`[Transcoder] ${input} → ${output} using ${codec}`);
}
}
class ThumbnailExtractor {
extract(input: string, timecodeSec: number): string {
const thumb = input.replace(/\.\w+$/, "_thumb.jpg");
console.log(`[Thumbnailer] extracted frame at ${timecodeSec}s → ${thumb}`);
return thumb;
}
}
class MetadataWriter {
write(filePath: string, meta: Record<string, string>): void {
console.log(`[Metadata] wrote to ${filePath}:`, meta);
}
}
// ── Options & result ───────────────────────────────────────────────────────────
export interface ConversionOptions {
outputFormat: "mp4" | "webm" | "mov";
thumbnailAt?: number; // seconds into video
metadata?: Record<string, string>;
}
export interface ConversionResult {
outputPath: string;
thumbnailPath: string | null;
detectedCodec: string;
}
// ── Facade ────────────────────────────────────────────────────────────────────
export class MediaConversionFacade {
private detector = new CodecDetector();
private transcoder = new VideoTranscoder();
private thumbnailer = new ThumbnailExtractor();
private metaWriter = new MetadataWriter();
convert(inputPath: string, opts: ConversionOptions): ConversionResult {
const codec = this.detector.detect(inputPath);
const outputPath = inputPath.replace(/\.\w+$/, `.${opts.outputFormat}`);
this.transcoder.transcode(inputPath, outputPath, codec);
const thumbnailPath =
opts.thumbnailAt !== undefined
? this.thumbnailer.extract(inputPath, opts.thumbnailAt)
: null;
if (opts.metadata) {
this.metaWriter.write(outputPath, opts.metadata);
}
return { outputPath, thumbnailPath, detectedCodec: codec };
}
}
// ── Usage ──────────────────────────────────────────────────────────────────────
const facade = new MediaConversionFacade();
const result = facade.convert("lecture.mkv", {
outputFormat: "mp4",
thumbnailAt: 5,
metadata: { title: "Lecture 1", author: "Prof. Smith" },
});
console.log("Done:", result);Facade Pattern Architecture
hourglass_empty
Rendering diagram...
lightbulb
Facade Pattern in the Real World
“A hotel concierge is a facade for the city’s complex infrastructure. Instead of you directly calling a taxi company, booking a restaurant, and arranging a museum ticket separately, the concierge handles all of it through a single conversation. The underlying services still exist in their full complexity—you just don’t deal with them directly.”