Home > GOF Pattern, java > GoF Patterns: Facade

GoF Patterns: Facade

2 marzo 2011

Translate in English with Google Translate
In questo articolo tratterò il pattern Facade.

Motivazione
Si tratta di un pattern strutturale basato su oggetti che viene utilizzato per nascondere la complessità del sistema e ridurre la comunicazione e la dipendenza del Client. L’utilizzo di questo pattern prevede di esporre una interfaccia per l’invocazione di un Sistema tale da semplificare l’invocazione ad opera del Client.

Immaginiamo di dovere interagire con un sistema e tale sistema preveda un numero complesso di relazioni. In uno scenario di questo tipo tutti i Client che intendono utilizzare le funzionalità del Sistema, devono conoscere le relazioni interne, per quanto complesse che siano. Nel momento in cui tali relazioni vengono modificate, tutti i Client devono essere notificati per apportare le modifiche del caso. Però in questo modo si verifica una alto accoppiamento tra Client e Sistema, cosa sbagliata! Come questa:

Senza Facade Pattern

Mancato utilizzo del Facade Pattern

Per ridurre l’alto accoppiamento, utilizzando questo pattern, introduciamo un Facade che mascheri la complessità e rappresenti l’anello di collegamento con il Sistema. In questo modo le eventuali modifiche verranno apportate in modo centralizzato al Facade senza impattare i singoli Client. Stiamo disaccoppiando, ossia tagliamo il legame forte che si era instaurato. Qualcosa di questo tipo:

Utilizzo di Facade Pattern

Utilizzo del Facade Pattern

Partecipanti e Struttura

Questo pattern è composto dai seguenti partecipanti:

  1. Facade: è il conoscitore del Sistema ed è colui che sarà responsabile dell’invocazione
  2. Sistema: è il Sistema che implementa la funzionalità; si prende l’incarico di eseguire il lavoro assegnato dall’oggetto Facade; non conosce il Facade e non mantiene alcuna referenza ad esso;

Possiamo schematizzare in UML con il Class Diagram:

Facade Pattern

Facade Pattern

Conseguenze

Tale pattern presenta i seguenti vantaggi/svantaggi:

  1. riduce il numero di associazioni: disaccoppiando il Client dal Sistema è possibile ridurre il numero di associazioni effettuate tra questi 2 attori, riducendo le interazioni.
  2. agevola il cambiamento : il basso accoppiamento rende possibile le modifiche al Sistema senza dover modificare anche il Client.
  3. non esclude l’uso diretto del Sistema : il Client può comunque utilizzare direttamente il Sistema se lo ritiene necessario. L’esistenza del Facade non esclude la possibilità di farlo: sempre che sappia come fare.

Implementazione

Come esempio pensiamo al caso in cui vogliamo assemblare un Computer. In questo caso abbiamo bisogno di alcuni componenti hardware che dovranno essere opportunamente collegati tra di loro, per esempio:

  • Alla scheda madre verranno collegati: CPU, RAM e scheda video.
  • Lo Chassis verrà utilizzato per contenere la scheda madre e per connettersi a tastiera, mouse e monitor.

Niente è casuale, occorre sapere come collegare le periferiche e le schede. In questo caso il nostro Client potrà prendersi l’incarico di effettuare tutte queste operazioni, ma per farlo dovrà sapere esattamente come, quindi dovrà conoscere le logiche del sistema cioè a cosa servono e come si collegano tra di loro.

Senza Facade Pattern

Senza Facade Pattern

 

Possiamo evitare che ciò si verifichi, come? Creando una classe Facade in cui spostiamo la logica delle relazioni tra le periferiche e le schede. Pertanto disaccoppiamo il Client con il Sistema. Le modifiche verranno gestite nella classe ComputerFacade, il Client vedrà il proprio lavoro semplificato in quanto la complessità gli verrà nascosta.

 

Con Facade Pattern
Con Facade Pattern

Vediamo per prima le classi che rappresentano le periferiche e le schede:

package patterns.facade;
public interface Device {}
package patterns.facade;
public class CPU implements Device {}
package patterns.facade;
public class RAM implements Device {}
package patterns.facade;
public class Videoboard implements Device {}
package patterns.facade;
public class Monitor implements Device {}
package patterns.facade;
public class Mouse implements Device {}
package patterns.facade;
public class Keyboard implements Device {}
package patterns.facade;

import java.util.ArrayList;

public class Motherboard implements Device {

    private ArrayList deviceList = new ArrayList();

    public void add(Device device){
        deviceList.add(device);
    }
}
package patterns.facade;

import java.util.ArrayList;

public class Chassis {

    private ArrayList deviceList = new ArrayList();
    private ArrayList connectionList = new ArrayList();

    public void add(Device device){
        deviceList.add(device);
    }
    public void conncection(Device device){
        connectionList.add(device);
    }

}

Nel caso di mancato utilizzo del pattern Facade, il Client si farà carico di gestire direttamente l’assemblaggio del Computer, in questo modo:

package patterns.facade;

public class Client {

    public static void main(String[] args) {
        Motherboard motherboard = new Motherboard();
        motherboard.add(new CPU());
        motherboard.add(new RAM());
        motherboard.add(new Videoboard());
        Chassis chassis = new Chassis();
        chassis.add( motherboard );
        chassis.conncection(new Monitor() );
        chassis.conncection(new Mouse() );
        chassis.conncection(new Keyboard() );
    }

}

Qualora implementiamo il pattern Facade, disaccopiamo Client e Sistema, creiamo una classe ComputerFacade nella quale inseriamo la logica e poi leghiamo il Client direttamente alla classe ComputerFacade.

package patterns.facade;

public class ComputerFacade {

    public Chassis createComputer() {
        Motherboard motherboard = new Motherboard();
        motherboard.add(new CPU());
        motherboard.add(new RAM());
        motherboard.add(new Videoboard());
        Chassis chassis = new Chassis();
        chassis.add(motherboard);
        chassis.conncection(new Monitor());
        chassis.conncection(new Mouse());
        chassis.conncection(new Keyboard());
        return chassis;
    }
}

Il Client si limiterà ad invocare ComputerFacade, non sarà più tenuto a conoscere i dettagli implementativi.

package patterns.facade;

public class Client {

    public static void main(String[] args) {
        Chassis chassis = new ComputerFacade().createComputer();
    }

}
Categorie:GOF Pattern, java
%d blogger cliccano Mi Piace per questo: