Qual è il nome del seguente pattern (anti)? Quali sono i suoi vantaggi e svantaggi?

28

Negli ultimi mesi, ho inciampato alcune volte sulla seguente tecnica / modello. Tuttavia, non riesco a trovare un nome specifico, né sono sicuro al 100% di tutti i suoi vantaggi e svantaggi.

Lo schema è il seguente:

All'interno di un'interfaccia Java, un insieme di metodi comuni viene definito come al solito. Tuttavia, utilizzando una classe interna, un'istanza predefinita viene divulgata tramite l'interfaccia.

public interface Vehicle {
    public void accelerate();
    public void decelerate();

    public static class Default {
         public static Vehicle getInstance() {
             return new Car(); // or use Spring to retrieve an instance
         }
    }
 }

Per me, sembra che il più grande vantaggio risieda nel fatto che uno sviluppatore deve solo conoscere l'interfaccia e non le sue implementazioni, ad es. nel caso voglia rapidamente creare un'istanza.

 Vehicle someVehicle = Vehicle.Default.getInstance();
 someVehicle.accelerate();

Inoltre, ho visto questa tecnica utilizzata insieme a Spring per fornire dinamicamente delle istanze a seconda della configurazione. A questo proposito, sembra che questo possa aiutare con la modularizzazione.

Tuttavia, non posso scuotere la sensazione che si tratti di un uso improprio dell'interfaccia poiché accoppia l'interfaccia con una delle sue implementazioni. (Principio di inversione delle dipendenze, ecc.) Qualcuno potrebbe spiegarmi come viene chiamata questa tecnica, nonché i suoi vantaggi & svantaggi?

Aggiornamento:

Dopo un po 'di tempo per riflettere, ho ricontrollato e ho notato che la seguente versione singleton del pattern è stata usata molto più spesso. In questa versione, un'istanza statica pubblica viene esposta attraverso l'interfaccia che viene inizializzata solo una volta (a causa del fatto che il campo è definitivo). Inoltre, l'istanza viene quasi sempre recuperata utilizzando Spring o uno stabilimento generico che disaccoppia l'interfaccia dall'implementazione.

public interface Vehicle {
      public void accelerate();
      public void decelerate();

      public static class Default {
           public static final Vehicle INSTANCE = getInstance();

           private static Vehicle getInstance() {
                return new Car(); // or use Spring/factory here
           }
      }
 }

 // Which allows to retrieve a singleton instance using...
 Vehicle someVehicle = Vehicle.Default.INSTANCE;

In breve: sembra che questo sia un modello personalizzato singleton / factory, che fondamentalmente permette di esporre un'istanza o un singleton attraverso la sua interfaccia. Rispetto agli svantaggi, alcuni sono stati nominati nelle risposte & commenti sotto. Finora, il vantaggio sembra essere nella sua convenienza.

    
posta Jérôme 15.12.2013 - 23:19
fonte

2 risposte

24

Default.getInstance è IMHO solo una forma molto specifica di un metodo di fabbrica , mescolato con una convenzione di denominazione presa da il modello singleton (ma senza essere un'implementazione di quest'ultimo). Nella forma attuale questa è una violazione del " principio di responsabilità singola ", perché l'interfaccia (che ha già lo scopo di dichiarando un'API classe) si assume la responsabilità aggiuntiva di fornire un'istanza predefinita, che sarebbe molto meglio posizionata in una classe VehicleFactory separata.

Il problema principale causato da questo costrutto è che induce una dipendenza ciclica tra Vehicle e Car . Ad esempio, nel modulo corrente non sarà possibile posizionare Vehicle in una libreria e Car in un'altra. Utilizzando una classe factory separata e ponendo il metodo Default.getInstance , si risolverebbe il problema. Potrebbe anche essere una buona idea dare a quel metodo un nome diverso, per evitare qualsiasi confusione legata ai singleton. Quindi il risultato potrebbe essere qualcosa di simile

VehicleFactory.createDefaultInstance()

    
risposta data 16.12.2013 - 08:49
fonte
3

Questo mi sembra Oggetto Null per me.

Ma ciò dipende in gran parte da come viene implementata la classe Car . Se è implementato in modo "neutro", allora è sicuramente un Oggetto Nullo. Ciò significa che se è possibile rimuovere tutti i controlli null sull'interfaccia e inserire l'istanza di questa classe invece di ogni occorrenza di null , il codice deve comunque funzionare correttamente.

Anche se è questo schema, non c'è alcun problema di creare un accoppiamento stretto tra l'interfaccia stessa e l'implementazione dell'oggetto nullo. Perché l'oggetto nullo può essere ovunque dove viene usata l'interfaccia.

    
risposta data 16.12.2013 - 12:26
fonte

Leggi altre domande sui tag