Alla ricerca di un modello Factory migliore (Java)

2

Dopo aver fatto un abbozzo di un modello di oggetto di alto livello, sto facendo un TDD iterativo e lasciando emergere gli altri oggetti come refactoring del codice (man mano che aumenta in complessità). (L'intero approccio può essere una discussione / argomento per un altro giorno.)

In ogni caso, sono al punto in cui sto cercando di ridefinire i blocchi di codice attualmente in un blocco if-else in oggetti separati. Questo perché esiste un'altra combinazione di valori che crea una nuova serie di sotto-rami logici.

Per essere più specifici, questa è una funzione del sistema di trading, in cui gli ordini di acquisto hanno un comportamento diverso rispetto agli ordini di vendita. Le risposte agli ordini hanno un campo indicatore numerico che descrive alcuni eventi che si sono verificati (ad esempio, riempire, cancellare). La combinazione di questo campo dell'indicatore numerico più se si tratta di un acquisto o di una vendita, richiede un'elaborazione diversa. Acquista il codice.

Creare una famiglia di oggetti per separare il codice per la gestione unica di ciascuna delle combinazioni dei 2 campi sembra una buona scelta a questo punto. Il modo in cui lo farei normalmente è creare un oggetto Factory che, richiamato con i 2 parametri rilevanti (indicatore, buysell), restituisca la sottoclasse corretta dell'oggetto. Alcune volte faccio questo modello con una mappa, che permette di cercare un'istanza dal vivo (o costruttore da usare tramite riflessione), e qualche volta faccio solo un codice rigido dei casi nella classe Factory.

Quindi - per qualche motivo questo non sembra un buon progetto (ad esempio un oggetto che conosce tutte le sottoclassi di un'interfaccia o un oggetto genitore) e un po 'goffo.

C'è un modello migliore per risolvere questo tipo di problema? E se questo approccio al metodo factory ha senso, qualcuno può suggerire un design più bello?

    
posta Sam Goldberg 13.03.2012 - 21:57
fonte

4 risposte

3

Il tuo approccio mi suona bene. Filosoficamente, mentre la tua officiale conosce di ogni sottoclasse, non sa sapere che conosce. In altre parole, in futuro le sottoclassi potrebbero essere generate altrove, in luoghi in cui la vostra fabbrica non sa (e se ne frega) nulla. Dall'altro lato, gli utenti di queste sottoclassi non sanno né si preoccupano da dove provengono. Potrebbe provenire dalla fabbrica , potrebbe provenire da qualche altra parte.

Il tuo brutto presentimento è che stai sostituendo un semplice meccanismo con uno stravagante, e non hai (ancora) veramente bisogno del potere che stai ricevendo. Potresti davvero perdere tempo. Ma se il tuo sistema cresce, potresti avere diverse fabbriche e molti altri oggetti potrebbero creare queste sottoclassi, incluse le sottoclassi stesse. Fintanto che la tua fabbrica non ha bisogno di sapere su tutte le sottoclassi, e fintanto che i tuoi "consumatori" non hanno bisogno di sapere quale fabbrica, se ce ne sono, loro venuto da, il tuo design è suono. Tutto è correttamente incapsulato e polimorfico.

Un'altra cosa: in Java più che in altre lingue, una sottoclasse spesso funziona meglio di un interruttore nella classe base. In Java sottoclassi qualsiasi cosa se ho bisogno di un comportamento leggermente diverso. In C #, farò un sacco di problemi per rendere una classe altamente flessibile con campi extra e parametri extra di costruzione. Una nuova classe Java può essere creata in un piccolo blocco di codice senza riferimenti altrove - una classe locale o anonima. In C # la nuova classe deve essere posizionata lontano dall'unico punto per fare riferimento ad essa come qualsiasi altra cosa che non sia la sua classe base - e potrebbe essere diversi livelli di base - o interfaccia.

    
risposta data 21.03.2012 - 21:52
fonte
2
> feels like not good design ... one object which knows 
> all the subclasses of an interface or parent object

Sono d'accordo con il tuo sentimento - questo viola il principio aperto aperto : ogni volta che implementi un nuovo handler devi cambia la fabbrica.

Una possibile soluzione è di invertire le dipendenze:

Ogni istanza si registra in fabbrica con i suoi parametri specifici. ora mai la classe conosce la fabbrica.

    
risposta data 13.03.2012 - 22:27
fonte
1

Una fabbrica centrale mi sembra una buona idea, poiché evita di avere la logica di quale oggetto scegliere si diffonde sul codice. Il problema rimanente che capisco deve essere risolto è come evitare questa classe factory conoscere tutte le classi derivate. Il modo in cui normalmente risolverei questo è che la classe factory sia un registro di tipi, con la quale intendo che sa dare il tipo giusto basandosi sull'interrogazione di una mappa di oggetti che gli viene fornita da un altro codice.

Potresti aggiungere alla tua classe base abstapract alcune funzioni che consentono alla factory di chiedere quale combinazione (indicatore, buy sell) gestisce. Quindi, quando ogni tipo viene registrato con la fabbrica, li chiama e aggiunge la combinazione come chiave alla mappa e l'istanza registrata come oggetto prototipo. Quindi, per ciascuna richiesta, visualizza i parametri nella mappa e clona l'oggetto prototipo.

La registrazione può essere effettuata in qualche codice di configurazione, che quindi sarebbe a conoscenza di tutti gli oggetti, o di diversi blocchi di codice ciascuno dei quali conosceva alcuni dei sottotipi.

    
risposta data 13.03.2012 - 22:28
fonte
1

Mi sembra adatto.

A proposito, gli oggetti che stai creando nelle tue fabbriche sono chiamati strategie . Determinare l'implementazione concreta della tua strategia suona come una buona pratica per una fabbrica per me. Non mi piace mai quel tipo di codice if / else che lo nasconde in una fabbrica rende più bello per tutto il codice client che vuole usare le strategie.

Come dici tu, stai usando TDD / design iterativo, quindi se una carenza nel design viene determinata in qualsiasi momento, allora migliorala.

    
risposta data 13.03.2012 - 22:37
fonte

Leggi altre domande sui tag