venerdì 28 novembre 2008

Adapter Design Pattern

ADAPTER DESIGN PATTERN:
Obiettivo: convertire una interfaccia esistente in una nuova interfaccia per ottenere compatibilità e riusabilità di classi non correlate in un' applicazione.

Nelle API java standard le classi che implementano il pattern Adapter sono facilmente riconoscibili (WindowAdapter, ComponentAdapter, MouseAdapter,...) . Come noto l'interfaccia WindowListener ha sette metodi:

public interface Windowlistener {
public void windowClosed(WindowEvent e);
public void windowOpened(WindowEvent e);
public void windowIconified(WindowEvent e);
public void windowDeiconified(WindowEvent e);
public void windowActivated(WindowEvent e);
public void windowDeactivated(WindowEvent e);
public void windowClosing(WindowEvent e);
}

Qualsiasi classe che implementa WindowListener dovrebbe necessariamente definire il contenuto di tutti questi metodi. La classe WindowAdapter implementa questa interfaccia con metodi tutti vuoti:

class WindowAdapter implements WindowListener{
    public void windowClosed(WindowEvent e){}
    public void windowOpened(WindowEvent e){}
    public void windowIconified(WindowEvent e){}
    public void windowDeiconified(WindowEvent e){}
    public void windowActivated(WindowEvent e){}
    public void windowDeactivated(WindowEvent e){}
    public void windowClosing(WindowEvent e){}
}

In questo modo in un'applicazione GUI, per esempio, una classe che ha bisogno di intercettare solo l'evento chiusura della finestra in cui è inserito un JFrame non deve implementare tutti i metodi presenti in WindowListener, ma solo il metodo public void windowClosed(WindowEvent e){} tramite la tecnica nota come Overriding.

class WindowClosingListener extends JFrame {
   public WindowClosingListener () {
        setSize(200, 200);
        setVisible(true);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("Closing event caught");
                System.exit(0);
            }
        });
    }
    public static void main(String[] args) {
        new WindowClosingListener();
    }
}

Un'altra applicazione di questo pattern (noto anche come Wrapper) è il riuso di classi e creazione di nuove classi compatibili con quelle già esistenti. Usando la composizione, per esempio, si potrebbe 'adattare' una classe già implementata e ben testata ad un nuovo sistema. La classe Adapter dovrà dichiarare tale classe gia esistente come variabile, tramite il meccanismo della composizione, e 'wrapparla' o 'fonderla' in se stessa.

import java.util.Date;
public class DataAdapter {
    private Date date;
    public DataAdapter() {
        date = new Date();
    }
    public DataAdapter(long date) {
        this.date = new Date(date);
    }
    public void setMillisecondi(long time) {
        date.setTime(time);
    }
    public long getMillisecondi() {
        return date.getTime();
    }
    public int confronta(DataAdapter anotherDate) {
        return date.compareTo(new Date(anotherDate.getMillisecondi()));
    }
    public boolean prima(DataAdapter when) {
        return date.before(new Date(when.getMillisecondi()));
    }
    public boolean dopo(DataAdapter when) {
        return date.after(new Date(when.getMillisecondi()));
    }
    @Override
    public String toString() {
        return date.toString();
    }
}


La classe DataAdapter può essere usata nel seguente modo:

    public static void main(String args[]) {
        DataAdapter data1 = new DataAdapter(1225446691789l);
        DataAdapter data2 = new DataAdapter(1225445322893l);
        if (data1.confronta(data2) == 0) {
            System.out.println("Le date coincidono");
        } else if (data1.confronta(data2) > 0) {
            System.out.println(data1 + " > " + data2);
        } else {
            System.out.println(data1 + " < " + data2);
        }
    }

Nessun commento: