Adapter - Wrapper

Pattern descritto in Design Pattern.

Lo scopo dell'Adapter é quello di permettere l'uso di una classe da parte di un'altra classe che non era stata pensata per interagire con quella, e che quindi si aspetta una diversa interfaccia.

Un esempio preso dalla vita reale é quello del nostro rasoio elettrico che possiamo usare in un albergo londinese solo a patto di adattare la presa della corrente inglese alla spina italiana.

Partecipanti
  • Client: utente delle funzionalità
  • Target: interfaccia che fornisce l'interfaccia al Client
  • Adaptee: l'interfaccia precedentemente esistente, non adatta al Client
  • Adapter: adatta l'interfaccia Adaptee a Target.
Esempio in Java

Immaginiamo di lavorare ad un applicazione che simuli un mondo fantasy. Ci sono uomini che mangiano e camminano e giganti che divorano e si muovono tre volte tanto quanto un uomo normale.

Fin qui tutto facile. Il fatto é che esistono anche strani esseri che a volte si comportano come uomini a volte come giganti. Costruiamo quindi un Adaptor che ci permetta di gestire questa situazione.

Un uomo rispetterà questa interfaccia:

public interface Man {
public void eat();
public void walk();
}

Un gigante seguirà invece questa:

public interface Giant {
public void devour();
public void bigWalk();
}

Questa classe definisce il comportamento di un uomo normale:

public class NormalMan implements Man {
public void eat() {
System.out.println("Eating something");
}

public void walk() {
System.out.println("Short walking");
}
}

Questa invece definisce un normale gigante:

public class NormalGiant implements Giant {
public void devour() {
System.out.println("Eating a lot");
}

public void bigWalk() {
System.out.println("Long walking");
}
}

E qui arriviamo al nostro Adaptor, uno strano essere uomo-gigante che estende l'uomo normale ma implementa l'interfaccia del gigante e definisce i metodi caratteristici del gigante in base a quelli dell'uomo:

public class ManGiant extends NormalMan implements Giant {
public void devour() {
System.out.println("A man eating like a giant:");
super.eat();
super.eat();
super.eat();
}

public void bigWalk() {
System.out.println("A man walking like a giant:");
super.walk();
super.walk();
super.walk();
}
}

A seguire un piccolo client per testare le funzionalità:

public class Main {
public static void main(String args[]) {
Man man = new NormalMan();
man.eat();
man.walk();

Giant giant = new NormalGiant();
giant.devour();
giant.bigWalk();

ManGiant mg = new ManGiant();

// now man-giant behaves like a giant
giant = mg;
giant.devour();
giant.bigWalk();

// now man-giant behaves like a man
man = mg;
man.eat();
man.walk();
}
}

Notiamo che il nostro uomo-gigante può comportarsi in entrambi i modi. Possiamo chiarire il suo comportamento in un dato momento usando l'interfaccia Man o Giant, invece di accedere direttamente all'oggetto.

Nessun commento:

Posta un commento