2009-12-14 8 views
5

vorrei:ServiceLocator e l'Open/Closed Principle

  1. Fai servizi visibili a tutte le classi che ne hanno bisogno,
  2. con un minimo di boilerplate, e
  3. spesso richiesta senza sacrificare la verificabilità !

È un progetto piccolo e penso che DI potrebbe essere eccessivo, ma forse mi sbaglio? In ogni caso, mi si sono concentrati sulla ServiceLocator pattern as described by Martin Fowler

In una classe cliente costruttore, ho qualcosa di simile:

this->db = Locator::getDb(); 
this->log = Locator::getLogger(); 

Poi il resto della classe metodi accedono al servizio tramite attributi tali Stati, ad esempio, :

this->fooModel = new fooModel(this->db); 
fooItem1234 = this->fooModel->findById(1234); 

Tuttavia vorrei anche questo livello di visibilità per gli oggetti "modello" (come sopra) fooModel perché sono accessibili da diversi luoghi diversi e non c'è bisogno di avere più di un'istanza.

Quindi il mio pensiero iniziale era di estendere Locator per avere un ::getFooModel() ma ora sembra che stia violando il Principio Aperto/Chiuso, dal momento che dovrò modificare Locator ogni volta che introdurre una nuova classe del modello.

Per soddisfare l'OCP, potrei utilizzare il Dynamic Service Locator (descritto anche sulla pagina di Fowler) tuttavia non sono totalmente venduto su questo per le stesse ragioni di lui, cioè non è abbastanza esplicito.

Un'altra soluzione sarebbe quella di rendere statici i metodi di tutti i miei modelli. Quindi:

fooItem1234 = FooModel::findById(1234); 

Mi piace perché è zero boilerplate. Posso solo creare una nuova classe di modelli e iniziare a chiamarla da qualsiasi luogo con una sola riga. Ma ora il modello dipende da Locator per trovare la sua connessione DB e non sono sicuro di come mi sento al riguardo. Per uno, se mai avessi bisogno di avere due fooModels aperti su connessioni di database separate, sarebbe un disastro e/o impossibile. Detto questo, attualmente non ho bisogno di farlo, quindi questa opzione sembra un po 'allettante.

Infine, c'è DI. Ma come ho detto sopra, penso che potrebbe essere troppo per questo piccolo progetto.

Conclusione: Sono un po 'bloccato qui e apprezzerei qualche consiglio dai guru di StackOverflow!

risposta

7

Perché pensi che DI sia eccessivo per il tuo progetto? I modelli DI come Costruttore Injection sono molto più semplici e più puliti di Service Locator (che considero un anti-pattern).

Ritengo che Service Locator sia un anti-pattern poiché è totalmente opaco all'utente dell'API che devono essere presenti le dipendenze; in questo modo, si potrebbero facilmente invocare metodi sui propri oggetti in un contesto in cui il Service Locator genererebbe, e l'API non ti dà assolutamente la certezza che questo è il caso.

Non è necessario un contenitore DI per utilizzare DI. Se hai solo un progetto semplice, puoi usare quello che è noto come DI di Poor Man quando colleghi le dipendenze manualmente.

+0

Sì, intendevo usare un contenitore quando ho detto che pensavo che DI sarebbe stato eccessivo, mi dispiace. E grazie per la risposta! Lo prendo quando dici Constructor Injection che stai dicendo che dovrei semplicemente passare i miei oggetti dbconn e logger nei costruttori delle classi che dipendono da loro? Se è così, questo è in realtà ciò che stavo facendo. Poi, per qualche ragione, ho deciso di dover aggiungere logger al prototipo di costruttore di ogni classe era male. Ma ora che mi hai fatto riflettere su questo, sembra avere molto più senso di quello che ho cercato di fare con questo ServiceLocator. – oops

+1

Fresco. Quindi, in genere ciò che dovresti fare è impilare o avvolgere le dipendenze. Probabilmente avrai molti servizi di basso livello, ma puoi spesso racchiudere due o tre di questi in oggetti significativi, e quindi iniettare solo uno di questi invece di tre servizi di basso livello. Puoi ripeterlo tutte le volte che vorresti mantenere basso il numero di dipendenze per le singole classi. –

+0

Che dire dello stack/wrapping di cose non totalmente correlate - come ad esempio il DBconn e il logger del mio esempio precedente - in un oggetto chiamato "config" o è una forma brutta? – oops

3

... e non è necessario disporre di più di un'istanza.

Stai mescolando mele e arance. Il fatto che tu abbia bisogno di una sola istanza di una classe per un'applicazione non è la stessa cosa che è una buona idea rendere tale istanza globalmente disponibile. Con DI non modifichi la cardinalità: c'è ancora una sola istanza. Quello che cambi è l'ambito delle variabili che indirizzano detta istanza. C'è una differenza.

Problemi correlati