Iteratori contro "cursori" in Java

5

In Java, la maggior parte delle persone si aspetta che ogni chiamata a Iterator.next() restituisca un oggetto distinto. Ciò ha portato alcuni di noi a definire un modello alternativo che abbiamo chiamato un "cursore". (Si noti che altri usano il termine "cursore" per tracciare una distinzione diversa). Il modello di un cursore è:

class SomeCursor {
    boolean hasNext();
    void next();
    type1 getItem1();
    type2 getItem2();
 }

In altre parole, è perfettamente chiaro che lo stesso oggetto si evolve in ogni fase dell'iterazione.

Il problema alla mano in questo momento è anche quello di supportare situazioni, come i servizi web, in cui vogliamo assolutamente oggetti distinti, in modo che possiamo spedire loro una collezione.

Mi fa pena immaginare coppie di classi (un cursore e un fagiolo) che devono essere mantenute in parallelo, e io sto cercando alternative.

Ecco un'idea, e mi chiedo se qualcun altro là fuori ne abbia visto uno migliore.

  1. Crei un'interfaccia costituita dai metodi 'ottieni' per un oggetto con tutti gli elementi in essa contenuti.
  2. Si definisce il cursore come implementante quell'interfaccia e inoltre haNext & successiva.
  3. Create dinamicamente gli oggetti bean usando al volo una delle principali librerie di code-gen dinamiche per creare una classe con i campi ovvi e ottenere metodi, oltre a metodi set, se necessario, per rendere felice qualcosa come JAX-B.

modifica: per coloro che non stanno seguendo, raccomando una lettura di link . Confronta anche con link , che è un esempio di questo 'cursore' approccio.

Nota in Lucene un'API che itera su una sequenza di oggetti, consente al chiamante di specificare se consegnare i nuovi dati a un nuovo oggetto o allo stesso vecchio oggetto ogni volta.

Sì, è possibile definire un Iterator<T> che restituisca la stessa cosa in qualsiasi momento, ma siamo preoccupati che le persone lo usino come arma per sparare le dita dei piedi. Quindi la preferenza per il modello JDBC-ish.

    
posta bmargulies 22.08.2011 - 19:42
fonte

3 risposte

2

Perdonami se non sto afferrando ciò che cerchi, ma sembra che tu stia confondendo i concetti di Iterator e Factory / Builder.

Lascia che ti mostri alcuni pensieri qui.

Il pattern Iterator funziona bene per una collezione omogenea di oggetti che vuoi distribuire attraverso un'interfaccia comune. Ad esempio, hai una collezione di stringhe e le vuoi distribuite in un ordine particolare in modo da utilizzare un comparatore (dietro le quinte) e il tuo codice che consuma deve solo chiamare next () un paio di volte per raggiungere il suo obiettivo.

Il pattern Factory crea un'istanza di un oggetto in base a una determinata specifica, talvolta fornita come argomenti, a volte dedotti. Il pattern Builder è simile ma di solito è orientato verso il completamento di un singolo passo lungo il percorso verso il completamento di un'istanza di una raccolta composita di oggetti.

Dal tuo esempio di codice sembra che tu voglia un meccanismo che ti permetta di creare un'istanza di un oggetto (di vario tipo) in risposta a un dato numero di chiamate. Forse una sequenza come questa:

next() -> getType1() -> String with "Hello"
next() -> getType2() -> Integer with 4
next() -> getTypeN() -> some function applied -> some type returned

e così via.

Se questo è ciò che stai cercando, allora questo approccio viola il Principio della Minima Sorpresa. Come sviluppatore, se un oggetto viene silenziosamente mutato dietro le quinte, mi piacerebbe saperlo poiché desidero conoscere i problemi di thread e prestazioni che potrebbero presentarsi.

Poiché il problema che si presenta è quello di mantenere una raccolta di oggetti tra chiamate Web senza stato, è preferibile utilizzare un elenco semplice e fornire l'indice alla voce corrente come parte della risposta al client. Quando il client richiede il contenuto dell'elenco, passa semplicemente a JAXB per eseguirne il marshalling in XML / JSON (utilizzerà un Iterator).

Questo approccio mantiene semplice il tuo codice, e quindi impedisce agli sviluppatori dopo aver guardato il codice e aver detto WTF?

    
risposta data 23.08.2011 - 10:34
fonte
1

Non vedo davvero la differenza tra ciò che hai lì e uno di Iterator<T> . Il fatto che tu voglia riciclare l'istanza sottostante su ogni iterazione è ancora legale, se non consigliato.

Potrebbe valere la pena guardare l'ultima presentazione di josh bloch. uno dei puzzle evoles attorno al EnumMap.entries() iterator riciclando la stessa istanza di Map.Entry per ogni voce, sicuramente infrange il principio della sorpresa minima.

    
risposta data 23.08.2011 - 10:28
fonte
0

Mi sembra che tu stia mescolando il concetto di iteratore con il concetto di proprietà del bean Java.

Se hai un'istanza di un bean e vuoi scorrere le sue proprietà, allora ci sono un certo numero di librerie che ti aiuteranno a farlo, come i comuni BeanUtils di Apache e Beanlib:

link

link

    
risposta data 23.08.2011 - 02:13
fonte

Leggi altre domande sui tag