Το Facade Pattern (Μοτίβο Πρόσοψης) ανήκει στα Structural Design Patterns (Δομικά Μοτίβα Σχεδιασμού). Ο κύριος στόχος του είναι να παρέχει μια απλή, ενιαία και εύχρηστη διεπαφή (interface) απέναντι σε ένα περίπλοκο σύστημα από κλάσεις ή API. Φανταστείτε το Facade σαν ένα υπάλληλο υποδοχής ξενοδοχείου, που αντί να μεριμνείτε εσείς για φαγητό, καθαρά σεντόνια ή ταξί, μιλάτε απευθείας μόνο με τον υπάλληλο αυτόν και εκείνος αναλαμβάνει να συντονίσει όλες τις εκκρεμότητες.
Ας υποθέσουμε ότι θέλετε να φτιάξετε ένα Home Theater. Για να δείτε μια ταινία, πρέπει χειροκίνητα να:
Αντί ο Client να καλεί πολλές διαφορετικές μεθόδους, θα φτιάξουμε ένα HomeTheaterFacade για τη διαχείριση του Home Theater.
// 1. Το σύστημα φωτισμού class TheaterLights { public void on() { System.out.println("Τα φώτα του δωματίου άναψαν."); } public void dim(int level) { System.out.println("Τα φώτα χαμήλωσαν στο " + level + "%."); } }
// 2. Ο προβολέας class Projector { public void on() { System.out.println("Ο προβολέας ενεργοποιήθηκε."); } public void off() { System.out.println("Ο προβολέας απενεργοποιήθηκε."); } public void wideScreenMode() { System.out.println("Ο προβολέας ρυθμίστηκε σε widescreen (16:9)."); } }
// 3. Το ηχοσύστημα class SoundSystem { public void on() { System.out.println("Το ηχοσύστημα ενεργοποιήθηκε."); } public void off() { System.out.println("Το ηχοσύστημα απενεργοποιήθηκε."); } public void setVolume(int level) { System.out.println("Η ένταση του ήχου ρυθμίστηκε στο " + level + "."); } }
// 4. Η πηγή της ταινίας (π.χ. Streaming Service) class StreamingPlayer { public void on() { System.out.println("Η συσκευή αναπαραγωγής ενεργοποιήθηκε."); } public void play(String movie) { System.out.println("Αναπαραγωγή της ταινίας: '" + movie + "'"); } public void stop() { System.out.println("Η ταινία σταμάτησε."); } public void off() { System.out.println("Η συσκευή αναπαραγωγής απενεργοποιήθηκε."); } }
Θα δημιουργήσουμε την κλάση Facade που λειτουργεί ως πρόσοψη στο περίπλοκο σύστημα ρυθμίσεων που περιγράψαμε.
public class HomeTheaterFacade { private TheaterLights lights; private Projector projector; private SoundSystem sound; private StreamingPlayer player; // Ο Constructor δέχεται τα αντικείμενα του υποσυστήματος public HomeTheaterFacade(TheaterLights lights, Projector projector, SoundSystem sound, StreamingPlayer player) { this.lights = lights; this.projector = projector; this.sound = sound; this.player = player; } // Απλοποιημένη μέθοδος για την εκκίνηση της ταινίας public void watchMovie(String movie) { System.out.println("\n--- Getting ready for the movie... ---"); lights.dim(10); projector.on(); projector.wideScreenMode(); sound.on(); sound.setVolume(20); player.on(); player.play(movie); System.out.println("--- Movie Started! ---\n"); } // Απλοποιημένη μέθοδος για τον τερματισμό public void endMovie() { System.out.println("\n--- Shuttting down Home Theater... ---"); lights.on(); projector.off(); sound.off(); player.stop(); player.off(); System.out.println("--- Done. ---\n"); } }
Δείτε πόσο απλός γίνεται ο κώδικας του πελάτη που χρησιμοποιεί την κλάση HomeTheaterFacade, καθώς δε χρειάζται να έχει καμία γνώση για το πως λειτουργεί εσωτερικά το σύστημα.
public class HomeTheaterUser { public static void main(String[] args) { // Δημιουργία των εξαρτημάτων του υποσυστήματος TheaterLights lights = new TheaterLights(); Projector projector = new Projector(); SoundSystem sound = new SoundSystem(); StreamingPlayer player = new StreamingPlayer(); // Δημιουργία της πρόσοψης HomeTheaterFacade homeTheater = new HomeTheaterFacade(lights, projector, sound, player); // Ο χρήστης με μία μόνο εντολή ξεκινάει την ταινία homeTheater.watchMovie("Inception"); // ... περνάει η ώρα και τελειώνει η ταινία ... // Ο χρήστης κλείνει τα πάντα με μία εντολή homeTheater.endMovie(); } }
💡 Σημείωση: Το Facade Pattern δεν κρύβει απαγορευτικά το υποσύστημα. Αν ένας Client θέλει να προσπεράσει το HomeTheaterFacade και να ρυθμίσει χειροκίνητα μόνο τα φώτα, έχει τη δυνατότητα να το κάνει.