2012-01-06 16 views
7

Sto arrivando a Java da C# dove gli eventi sono cittadini di prima classe e gestori di eventi possono essere metodi privati. Ora sto lavorando a un progetto Java in cui ovviamente ho bisogno di utilizzare un pattern Observer per implementare eventing.Evitare di esporre i dettagli di implementazione quando si implementa un pattern di osservatore in Java?

Poiché l'Observer deve esporre i suoi metodi di callback listener/handler alla classe Observable, sembra che questo esponga l'implementazione dei dettagli dell'Observer ad altre classi non interessate. Posso impostare l'accesso a questi metodi a livello di pacchetto che mantenga questi dettagli di implementazione nascosti agli utenti del mio pacchetto, ma ha ancora un cattivo "odore" per me.

È solo questo qualcosa che ho bisogno di stringere i denti e nudo o c'è un modo migliore?

risposta

9

Con il pattern Observer le classi che stanno osservando non hanno bisogno di esporre le loro implementazioni. Spesso la tua classe che sta notificando le altre classi avrà la sua interfaccia associata per le altre classi da implementare.

public interface Observer 
{ 
    public void handleSomeEvent(Object someObjectOfImportance); 
} 

public class Observable 
{ 
    public void register(Observer observer); 
} 

Ogni classe può implementare l'interfaccia Observer e registrare se stesso senza esporre alcun dettagli di implementazione. Esporre che implementa un'interfaccia, ma che non specifica come lo implementa. In alternativa, potresti fornire un'implementazione anonima.

public class SomeObserverImplementation implements Observer 
{ 
    public void handleSomeEvent(Object someObjectOfImportance) 
    { 
     // I can do whatever I want here 
    } 
} 

Aggiornamento Se siete preoccupati che la classe ora è esponendo una nuova interfaccia ci sono alcuni modi di lavorare intorno ad esso. Uno è quello di creare un'implementazione anonima. Un altro è che puoi avere una classe interna privata che implementa l'interfaccia Observable.

public class IDontWantOthersToKnowIObserve 
{ 
    private class HiddenObserver implements Observer 
    { 
     public void handleSomeEvent(Object someObjectOfImportance) 
     { 
      ... 
     } 
    } 

    ... in some method ... 
    theObservable.register(myHiddenObserver); 
} 

Per utilizzare un'implementazione anonimo:

theObservable.register(new Observer() 
      { 
       public void handleSomeEvent(Object someObjectOfImportance) 
       { 
           // ... 
       } 
      }); 
+0

Grazie! Bella risposta! – HolySamosa

1

In Java questo non è normalmente pensato come in realtà esporre i dettagli di implementazione, tuttavia, se si vuole veramente nascondere la funzionalità della vostra classe da altre classi quindi è necessario che la classe implementa interfacce diverse che espongono solo un sottoinsieme della funzionalità complessiva della classe. Se poi assicuri che le altre classi accedano alla tua classe solo attraverso una particolare interfaccia (possibilmente tramite una fabbrica), allora nascondi efficacemente la tua implementazione.

es:

public interface Observer<T> 
{ 
    public void notify(T event); 
} 

public interface PublicFace 
{ 
    public void doSomething(); 
} 

public class SomeClass implements Observer<Event>, PublicFace 
{ 
    public void notify(Event event) 
    { 
    // ... 
    } 

    public void doSomething() 
    { 
    // ... 
    } 
} 

public class FaceFactory 
{ 
    public static PublicFace getPublicFaceInstance() 
    { 
    return new SomeClass(); 
    } 
} 
Problemi correlati