2009-07-30 14 views
6

È meglio spiegare la domanda con un esempio. Possiedo un modello di interfaccia che può essere utilizzato per accedere ai dati. Possono esserci diverse implementazioni di Model che possono rappresentare i dati in vari formati come XMl, formato txt ecc. Il modello non riguarda i formati. Diciamo che una tale implementazione è myxmlModel.Forza modello Singleton su una classe che implementa un'interfaccia

Ora voglio forzare myxmlModel ed ogni altra realizzazione di Modello seguire Singleton pattern .Il solito modo è quello di rendere myxmlModels costruttore privato e fornire un metodo factory statico per restituire un'istanza di MyModel class.Ma il problema è l'interfaccia non può avere definizioni di metodo statico e un risultato non posso applicare una particolare definizione del metodo Factory su tutte le implementazioni di Modello. Pertanto, un'implementazione può terminare con la fornitura di getObject() e altri potrebbero avere NewModel()..

Un lavoro intorno è quello di consentire l'accesso al pacchetto costruttore di myxmlModel e creare una classe di fabbrica che crea il myxmlModel oggetto e memorizzare nella cache per un ulteriore uso.

Mi chiedevo se esiste un modo migliore per ottenere la stessa funzionalità.

risposta

0

Puoi refactoring l'interfaccia per essere una classe astratta? Ciò ti consentirà di forzare un particolare metodo factory su tutte le classi di implementazione.

+0

Provato. La classe astratta non funziona – Duleb

+1

Il polimorfismo non funziona in caso di metodo statico. Vedi se hai un metodo statico in classe astratta e lo sostituisci in sottoclasse, quindi se provi ad accedere a quel metodo quello originale verrebbe chiamato non il metodo della sottoclasse. – Duleb

+0

Ahhh, certo, mi dispiace per quello. – Steven

4
  1. Fabbrica una fabbrica che restituisce le istanze dell'interfaccia, Modello, .
  2. Effettuare tutte le implementazioni concrete del pacchetto modello: classi private nello stesso pacchetto della fabbrica.
  3. Se il modello deve essere un singleton e si utilizza java 5+, utilizzare enum invece del tradizionale singleton, in quanto è più sicuro.
public enum MyXMLModel{ 
INSTANCE(); 
//rest of class 
}; 

EDIT: Un'altra possibilità è quella di creare le classi dei delegati che fanno tutto il lavoro e quindi utilizzare un enum per fornire tutte le Opzioni modello.

per esempio:

class MyXMLModelDelegate implements Model { 
public void foo() { /*does foo*/} 
... 
} 

class MyJSONModelDelegate implements Model { 
public void foo() { /*does foo*/ } 
... 
} 

public enum Models { 
XML(new MyXMLModelDelgate()), 
JSON(new MyJSONModelDelegate()); 

private Model delegate; 
public Models(Model delegate) { this.delegate=delegate; } 

public void foo() { delegate.foo(); } 
} 
+0

La fabbrica va bene. Ma sono curioso di sapere se è possibile ottenere la stessa funzionalità senza Factory. – Duleb

+0

Sto lavorando su eclipse. L'interfaccia del modello è il contratto per il punto di estensione. L'implementazione del modello è l'estensione. Quindi ho bisogno di esporre il myxmlModel.Se espongo un po 'di classe Factory, dato che non implementerà Model, il Contratto fallirà. – Duleb

0

ho usato per pormi la stessa domanda. E ho proposto la stessa risposta ;-)

Ora, di solito trascuro il comportamento di "forzatura", mi affido alla documentazione. Non ho trovato casi in cui l'aspetto di Singleton fosse così convincente da dover essere applicato con tutti i mezzi. È solo una "best practice" per il progetto.

Io di solito uso Spring per installare un tale oggetto, ed è la configurazione Spring che lo rende un Singleton. Sicuri, e così facile ... più vantaggi Spring aggiuntivi (come Proxying, sostituendo un oggetto diverso una volta per fare alcuni test ecc ...)

0

Questa è più una risposta al tuo commento/chiarimento alla risposta di kts. È così, che il vero problema non è l'utilizzo del pattern Singleton, ma la definizione di uno schema di punti di estensione di eclissi (equinozio) che consente di contribuire a un singleton?

Penso che questo non può essere fatto, perché ogni volta che si chiama IConfigurationElement.createExecutableExtension si crea una nuova istanza. Questo è abbastanza incompatibile con il tuo requisito singleton. E quindi è necessario il costruttore pubblico predefinito in modo che tutti possano creare istanze.

A meno che non si può cambiare la definizione punto di estensione in modo che i plugin contribuiscono a ModelFactory piuttosto che un modello, come

public interface ModelFactory { 

    public Model getModelInstance(); 

} 

Così l'utente dell'interno sarà un'istanza di un ModelFactory e utilizzarlo per ottenere il Singleton.

Se ho indovinato sbagliato, lasciare un commento e posso cancellare la risposta;)

+0

Sì, hai ragione. Ma se espongo la classe di fabbrica, allora il Contratto (vale a dire per implementare l'interfaccia Modello) fallirà. Esistono molti altri metodi in IConfigurationElement che possiamo usare per ottenere maggiori informazioni sull'estensione, magari ottenere il nome della classe e richiamare un metodo statico su di esso per ottenere un oggetto. Ma poi di nuovo torniamo al punto di partenza. Non possiamo avere una dichiarazione statica nell'interfaccia del modello. – Duleb

+0

Non esattamente - il contratto viene semplicemente spostato nella classe ModelFactory. Ora avrai due contratti: la fabbrica (contributo tramite il punto di estensione) e il modello (la fabbrica deve restituire un'implementazione del modello) –

2

È possibile utilizzare la riflessione. Qualcosa di simile a questo:

public interface Model { 
    class Singleton { 
    public static Model instance(Class<? extends Model> modelClass) { 
     try { 
     return (Model)modelClass.getField("instance").get(null); 
    } catch (blah-blah) { 
     blah-blah 
    } 
    } 
} 

public class XmlModel implements Model { 
    private static final Model instance = new XmlModel(); 

    private XmlModel() { 
    } 
} 

utilizzo:

Model.Singleton.instance(XmlModel.class) 

In realtà, non mi piace questo codice tanto :). In primo luogo, utilizza la riflessione - molto lento, in secondo luogo - ci sono possibilità di errori di runtime in caso di definizioni errate delle classi.

+0

Penso che la riflessione funzionerà. – Duleb

Problemi correlati