User Tools

Site Tools


oop:facade_pattern

Facade Pattern

Το Facade Pattern (Μοτίβο Πρόσοψης) ανήκει στα Structural Design Patterns (Δομικά Μοτίβα Σχεδιασμού). Ο κύριος στόχος του είναι να παρέχει μια απλή, ενιαία και εύχρηστη διεπαφή (interface) απέναντι σε ένα περίπλοκο σύστημα από κλάσεις ή API. Φανταστείτε το Facade σαν ένα υπάλληλο υποδοχής ξενοδοχείου, που αντί να μεριμνείτε εσείς για φαγητό, καθαρά σεντόνια ή ταξί, μιλάτε απευθείας μόνο με τον υπάλληλο αυτόν και εκείνος αναλαμβάνει να συντονίσει όλες τις εκκρεμότητες.

Παράδειγμα - Home Theater Automation Service

Ας υποθέσουμε ότι θέλετε να φτιάξετε ένα Home Theater. Για να δείτε μια ταινία, πρέπει χειροκίνητα να:

  • Nα χαμηλώσετε τα φώτα.
  • Να ενεργοποιήσετε τον προβολέα (Projector).
  • Να ενεργοποιήσετε το ηχοσύστημα (Sound System) και να ρυθμίσετε την ένταση.
  • Να ξεκινήσετε την αναπαραγωγή της ταινίας.

Αντί ο Client να καλεί πολλές διαφορετικές μεθόδους, θα φτιάξουμε ένα HomeTheaterFacade για τη διαχείριση του Home Theater.

TheaterLights.java
// 1. Το σύστημα φωτισμού
class TheaterLights {
    public void on() { System.out.println("Τα φώτα του δωματίου άναψαν."); }
    public void dim(int level) { System.out.println("Τα φώτα χαμήλωσαν στο " + level + "%."); }
}
Projector.java
// 2. Ο προβολέας
class Projector {
    public void on() { System.out.println("Ο προβολέας ενεργοποιήθηκε."); }
    public void off() { System.out.println("Ο προβολέας απενεργοποιήθηκε."); }
    public void wideScreenMode() { System.out.println("Ο προβολέας ρυθμίστηκε σε widescreen (16:9)."); }
}
SoundSystem.java
// 3. Το ηχοσύστημα
class SoundSystem {
    public void on() { System.out.println("Το ηχοσύστημα ενεργοποιήθηκε."); }
    public void off() { System.out.println("Το ηχοσύστημα απενεργοποιήθηκε."); }
    public void setVolume(int level) { System.out.println("Η ένταση του ήχου ρυθμίστηκε στο " + level + "."); }
}
StreamingPlayer.java
// 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 που λειτουργεί ως πρόσοψη στο περίπλοκο σύστημα ρυθμίσεων που περιγράψαμε.

HomeTheaterFacade.java
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, καθώς δε χρειάζται να έχει καμία γνώση για το πως λειτουργεί εσωτερικά το σύστημα.

HomeTheaterUser.java
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();
    }
}

Πλεονεκτήματα:

  • Μείωση Πολυπλοκότητας: Απομονώνει τον Client από τα πολύπλοκα υποσυστήματα.
  • Χαλαρή Σύζευξη (Loose Coupling): Αν αύριο αλλάξει ο τρόπος που λειτουργεί το SoundSystem, θα χρειαστεί να αλλάξει μόνο η κλάση Facade και όχι ολόκληρη η εφαρμογή μας.
  • Ευκολία στη χρήση: Ιδανικό όταν ενσωματώνουμε μεγάλες, κακογραμμένες ή παλιές (legacy) βιβλιοθήκες τρίτων.

💡 Σημείωση: Το Facade Pattern δεν κρύβει απαγορευτικά το υποσύστημα. Αν ένας Client θέλει να προσπεράσει το HomeTheaterFacade και να ρυθμίσει χειροκίνητα μόνο τα φώτα, έχει τη δυνατότητα να το κάνει.

oop/facade_pattern.txt · Last modified: 2026/05/25 11:29 by gthanos