Facade (Fasad)
Introduktion
Facade är ett strukturmönster som tillhandahåller ett förenklat gränssnitt till ett bibliotek, ett ramverk eller en komplex uppsättning klasser.
Problem
Tänk dig att du måste få din kod att fungera med ett komplext videokonverteringsramverk. För att konvertera en fil behöver du initiera en VideoFile, hämta rätt codec via CodecFactory, läsa och konvertera bitrate via BitrateReader och mixa om ljudet med AudioMixer — allt i rätt ordning med rätt beroenden.
Affärslogiken i din app blir hårt kopplad till dessa implementationsdetaljer, koden svår att förstå och varje förändring i ramverket riskerar att ha sönder din kod.
Lösning
En Facade erbjuder ett enkelt gränssnitt till det komplexa delsystemet. Den innehåller precis de funktioner klienten bryr sig om och döljer alla rörliga delar bakom en enda, väldefinierad ingångspunkt.
När ska Facade användas?
- När du behöver ett enkelt gränssnitt till ett komplext delsystem.
- När du vill strukturera ett delsystem i lager med tydliga ingångspunkter.
- När du vill minska beroenden mellan flera delsystem.
Struktur
| Roll | Ansvar |
|---|---|
| Facade | Tar emot klientens begäran och koordinerar delsystemet. |
| Subsystem-klasser | Innehåller den faktiska logiken; känner inte till Facade. |
| Klient | Anropar bara Facade — behöver inte känna till delsystemet. |
Exempel — Videokonverterare (Java)
Scenariot: En VideoConversionFacade döljer ett komplext ramverk för videokonvertering. Klienten behöver bara anropa en metod.
// ── Subsystem-klasser ──────────────────────────────────────
public class VideoFile {
private String filename;
private String codecType;
public VideoFile(String filename) {
this.filename = filename;
this.codecType = filename.substring(filename.indexOf(".") + 1);
}
public String getFilename() { return filename; }
public String getCodecType() { return codecType; }
}
public class CodecFactory {
public static Codec extract(VideoFile file) {
String type = file.getCodecType();
if (type.equals("mp4")) {
System.out.println("CodecFactory: extracting MPEG4 audio codec...");
return new MPEG4CompressionCodec();
} else {
System.out.println("CodecFactory: extracting OGG audio codec...");
return new OggCompressionCodec();
}
}
}
public interface Codec {}
public class MPEG4CompressionCodec implements Codec { public String type = "mp4"; }
public class OggCompressionCodec implements Codec { public String type = "ogg"; }
public class BitrateReader {
public static VideoFile read(VideoFile file, Codec codec) {
System.out.println("BitrateReader: reading file...");
return file;
}
public static VideoFile convert(VideoFile buffer, Codec codec) {
System.out.println("BitrateReader: converting bitrate...");
return buffer;
}
}
public class AudioMixer {
public File fix(VideoFile result) {
System.out.println("AudioMixer: fixing audio...");
return new File("tmp");
}
}
// ── Facade ────────────────────────────────────────────────
public class VideoConversionFacade {
public File convertVideo(String fileName, String format) {
System.out.println("\nVideoConversionFacade: starting conversion...");
VideoFile file = new VideoFile(fileName);
Codec sourceCodec = CodecFactory.extract(file);
Codec destinationCodec;
if (format.equals("mp4")) {
destinationCodec = new MPEG4CompressionCodec();
} else {
destinationCodec = new OggCompressionCodec();
}
VideoFile buffer = BitrateReader.read(file, sourceCodec);
VideoFile intermediateResult = BitrateReader.convert(buffer, destinationCodec);
File result = new AudioMixer().fix(intermediateResult);
System.out.println("VideoConversionFacade: conversion completed.");
return result;
}
}
// ── Klientkod ─────────────────────────────────────────────
public class Application {
public static void main(String[] args) {
VideoConversionFacade converter = new VideoConversionFacade();
// Klienten anropar bara EN metod — delsystemets komplexitet är dold
File mp4 = converter.convertVideo("funny-cats.ogg", "mp4");
}
}
Fördelar
- Isolerar din kod från ett komplext delsystem.
- Reducerar antalet beroenden mellan klienten och delsystemet.
- Lättare att byta ut delsystemet utan att påverka klientkoden.
Nackdelar
- En Facade kan riskera att bli ett “God Object” — kopplad till för många klasser.
Av Victor Hernandez från Bytebase.se