Iteration Context è un pattern? Dovrebbe essere?

2

Quello che segue è più un'affermazione che una domanda - descrive qualcosa che può essere un modello. La domanda è: è un modello noto? Oppure, se non lo è, dovrebbe essere?

Ho avuto una situazione in cui ho dovuto scorrere su due strutture di dati multistrato diverse e copiare le informazioni da una all'altra. A seconda del caso d'uso particolare, avevo circa otto diversi tipi di livelli, combinati in circa otto diverse combinazioni:

A-B-C
B-C
A-C
D-E
A-D-E

e così via

Dopo alcuni tentativi infruttuosi di calcolare la ripetizione del codice di iterazione per livello, mi sono reso conto che la difficoltà principale in questo refactoring era il fatto che il livello più basso richiedeva l'accesso ai dati raccolti a livelli più alti. Per soddisfare esplicitamente questo requisito, ho introdotto la classe IterationContext con un numero di metodi get() e set() per l'accumulo delle informazioni necessarie.

Alla fine, ho avuto la seguente struttura di classe:

class Iterator {
  virtual void iterateOver(const Structure &dataStructure1, IterationContext &ctx) const = 0;
};

class RecursingIterator : public Iterator {
  RecursingIterator(const Iterator &below);
};


class IterateOverA : public RecursingIterator {
  virtual void iterateOver(const Structure &dataStructure1, IterationContext &ctx) const {
    // Iterate over members in dataStructure1
      // locate corresponding item in dataStructure2 (passed via context)
      // and set it in the context
      // invoke the sub-iterator
};

class IterateOverB : public RecursingIterator {
  virtual void iterateOver(const Structure &dataStructure1, IterationContext &ctx) const {
    // iterate over members dataStructure2 (form context)
      // set dataStructure2's item in the context
      // locate corresponding item in dataStructure2 (passed via context)
      // invoke the sub-iterator
};


void main() 
{
  class FinalCopy : public Iterator {
      virtual void iterateOver(const Structure &dataStructure1, IterationContext &ctx) const {
          // copy data from structure 1 to structure 2 in the context,
          // using some data from higher levels as needed
      }
   }

  IterationContext ctx(dateStructure2);
  IterateOverA(IterateOverB(FinalCopy())).iterate(dataStructure1, ctx);
}

Accade quindi che dataStructure1 sia una struttura dati uniforme, simile al DOM XML, mentre dataStructure2 è una struttura di dati legacy composta da vari struct s e matrici. Ciò mi consente di passare dataStructure1 al di fuori del contesto per comodità. In generale, entrambi i lati dell'iterazione o entrambi i lati possono essere passati tramite il contesto, come conveniente.

I punti chiave della situazione sono:

  • codice complicato che deve essere richiamato in "layers", con più combinazioni di tipi di layer possibili
  • nel livello inferiore, le informazioni dei livelli superiori devono essere visibili.

I punti chiave dell'implementazione sono:

  • uso della classe di contesto per accedere ai dati da tutti i livelli di iterazione
  • codice di iterazione complicato incapsulato nell'implementazione della pura funzione virtuale
  • due interfacce: una a conoscenza dell'iteratore sottostante, di cui non si è a conoscenza.
  • uso di const & per semplificare la sintassi dell'utilizzo
posta Arkadiy 07.04.2011 - 14:41
fonte

4 risposte

1

Non so davvero se questo è uno schema, ma esiste già un modello di progettazione che può aiutarti (credo) a realizzare ciò che desideri con quella struttura dati.

Il pattern è chiamato Iterator (è un modello comportamentale presentato nel libro "Pattern di progettazione: elementi di riutilizzabile software orientato agli oggetti" di Gang of Four), fornisce un modo per accedere agli elementi di un oggetto aggregato in sequenza senza esponendo la sua rappresentazione sottostante. Ti consiglio di dargli un'occhiata, potrebbe essere che ti può aiutare.

    
risposta data 23.07.2011 - 23:06
fonte
1

Il pattern che vedo è il pattern Decorator in cui hai una classe che esegue il lavoro ( FinalCopy ) che può essere 'decorato' dalle classi IterateOverA e IterateOverB . Le classi 'decorative' aumentano la classe FinalCopy eseguendo attività aggiuntive prima e dopo le invocazioni su di essa. Poiché tutte e tre queste classi implementano la stessa interfaccia ( Iterator ), sono intercambiabili e il cliente non deve sapere del proprio nidificazione.

    
risposta data 22.10.2011 - 02:41
fonte
0

Il pattern che descrivi al momento sembra fare diverse cose intrecciate. Quindi potresti definirlo come un nuovo modello per un caso molto specifico di attraversamento diretto di un certo tipo di linguaggio (perché è fondamentalmente ciò che è un ordinamento delle strutture dati), ma probabilmente è più facile dividerlo.

Un esempio per affrontare questo: l'ordinamento di strutture di dati separate che enumerate rientrano in alcune classi di linguaggio (assomiglia a un linguaggio normale mentre lo descrivi, ma il nesting suona come potrebbe anche essere espresso come contesto -la lingua libera o un linguaggio sensibile al contesto se il contenuto di alcune strutture di dati definisce ciò che segue dopo.

Sulla base della qualifica della lingua, è possibile definire una grammatica e usarla per utilizzare uno qualsiasi degli algoritmi di analisi esistenti per trasformare i dati che si incontrano in un albero di sintassi astratto (AST) e attraversare quello che usa il visitatore o interprete-modello.

Puoi dividerlo ulteriormente sviluppando più visitatori o interpreti per implementare i passaggi separati necessari per copiare i dati (o eseguire qualsiasi altra azione).

    
risposta data 19.04.2011 - 10:52
fonte
0

Non ne so abbastanza di quello che stai facendo, ma sembrerebbe più pratico avere qualcosa a monte che possa essere usato come prototipo per la generazione di entrambe le strutture di dati. Il fatto che stai copiando i dati tra due strutture dati dice che qualcosa non va, perché è una violazione di DRY.

Se non è possibile prototipare le 2 strutture dati, un'altra opzione sarebbe quella di creare un delegato per la struttura dati legacy che restituisce i valori da quella struttura in un modo atteso.

    
risposta data 24.05.2011 - 18:00
fonte

Leggi altre domande sui tag