& # 8220; Set di definizioni negoziato & # 8221; modello di progettazione & # 8212; ben noto con un altro nome?

StackOverflow https://stackoverflow.com/questions/401720

Domanda

In un progetto in cui sono stato coinvolto per molti anni, ho gradualmente sviluppato un modello di progettazione che si è rivelato estremamente utile per me. A volte sento che dovrei diventare un po 'evangelico, ma sarei un po' imbarazzato se provassi e scoprissi che era solo la mia versione del vecchio cappello di qualcuno. Ho cercato Design Patterns cercandolo invano, e non ho mai incontrato nessuno che ne parlava, ma la mia ricerca non è stata esaustiva.

L'idea principale è avere un oggetto broker che gestisca un insieme di oggetti di definizione, ogni oggetto di definizione che costituisce un possibile valore di qualche proprietà complessa. Ad esempio, potresti avere classi Car, Plane e Generator che hanno tutte un EngineType. L'auto non memorizza il proprio oggetto EngineType, memorizza una chiave di riferimento di qualche tipo che indica il tipo di Engine che ha (come un numero intero o un ID stringa). Quando vogliamo esaminare le proprietà o il comportamento di un EngineType, diciamo WankelEngine, chiediamo all'oggetto singleton EngineTypeBroker l'oggetto di definizione di WankelEngine, passandogli la chiave di riferimento. Questo oggetto racchiude tutto ciò che è interessante sapere su EngineTypes, probabilmente semplicemente un elenco di proprietà ma potenzialmente caricato anche su di esso.

Quindi ciò che facilita è una specie di aggregazione condivisa, liberamente accoppiata, in cui molte auto possono avere un WankelEngine ma c'è solo un oggetto di definizione WankelEngine (e EngineTypeBroker può sostituire quell'oggetto, sfruttando l'accoppiamento libero in un morfismo runtime migliorato ).

Alcuni elementi di questo modello mentre lo uso (continuando a usare EngineType come esempio):

  1. Esistono sempre funzioni IsEngineType (x) e EngineType (x), per determinare se un determinato valore è una chiave di riferimento valida per un EngineType e per recuperare l'oggetto di definizione EngineType corrispondente a una chiave di riferimento, rispettivamente.
  2. Consento sempre più forme di chiave di riferimento per un determinato EngineType, sempre almeno un nome di stringa e l'oggetto di definizione stesso, il più delle volte un ID intero, e talvolta tipi di oggetti che aggregano un EngineType. Questo aiuta con il debug, rende il codice più flessibile e, nella mia situazione particolare, facilita molti problemi di compatibilità con le versioni precedenti rispetto alle pratiche precedenti. (Il solito modo in cui le persone facevano tutto questo, nel contesto di questo progetto, era definire gli hash per ogni proprietà che un EngineType poteva avere e cercare le proprietà in base alla chiave di riferimento.)
  3. Di solito, ogni istanza di definizione è una sottoclasse di una classe generale per quel tipo di definizione (ovvero WankelEngine eredita EngineType). I file di classe per gli oggetti di definizione sono conservati in una directory come / Def / EngineType (ovvero la classe di WankelEngine sarebbe / Def / EngineType / WankelEngine). Pertanto, le definizioni correlate sono raggruppate insieme e i file di classe assomigliano ai file di configurazione per EngineType, ma con la possibilità di definire il codice (generalmente non presente nei file di configurazione).

Alcuni pseudocodici di esempio banalmente illustrativi:

class Car {

    attribute Name;
    attribute EngineTypeCode;

    object GetEngineTypeDef() {
        return EngineTypeBroker->EngineType(this->GetEngineTypeCode());
    }

    string GetDescription() {
        object def = this->GetEngineTypeDef();
        return "I am a car called " . this->GetName() . ", whose " .
            def->GetEngineTypeName() . " engine can run at " .
            def->GetEngineTypeMaxRPM() . " RPM!";
    }

}

Quindi, c'è un nome là fuori per questo?

È stato utile?

Soluzione

SingletonRegistry

Credimi o no. Stavo pensando la stessa cosa stamattina.

Ho usato questo modello prima ma non ho mai trovato un riferimento per esso né so come nominarlo.

Penso che sia un tipo di " Keyed " singleton, dove le istanze sono memorizzate da qualche parte e sono ottenute usando una chiave.

L'ultima volta che l'ho usato è stato per recuperare dati da diverse fonti.

Avevo circa 50 tabelle di database (renderlo 10) E ho un front-end "table" dove i dati dovevano essere visualizzati, ma i dati potevano provenire da una qualsiasi di quelle fonti e ognuna richiedeva una logica diversa (query, join, chiavi, ecc.)

Questo front-end era "configurabile" quindi non potevo sapere quali valori dovevano essere mostrati e quali altri no.

La soluzione era quella di prendere il columnName (nel front-end) come chiave e ottenere l'istanza corretta per creare la query giusta.

Questo è stato installato in una mappa di hash all'inizio e successivamente recuperato da una tabella di database.

Il codice era così:

class DataFetcher {
    abstract Object getData( Object id );
}

class CustomerNameDataFetcher extends DataFetcher {
    Object getData( Object customerId ) { 
        // select name from customer where id = ? 
     }
}

class CompanyAdressDataFetcher extends DataFetcher { 
     Object getData( Object customerId ) { // don't ask why.
          // select name from company , customer where customer.co = company.co and cu = ?  etc.
     }
} 

class ProductColor extends DataFetcher { 
     Object getData( Object x ) { 
     // join from customer to color, to company to season to a bunch of table where id = ? 
}

// And the list goes on.

Ogni sottoclasse ha usato una logica diversa.

In fase di esecuzione l'utente ha configurato la sua vista e seleziona ciò che desidera vedere.

Quando l'utente ha selezionato le colonne per vedere, ho usato il nome della colonna e un ID per recuperare i dati.

I DataFetcher erano tutti installati nella classe genitore (per questo non volevo avere una classe separata) in un metodo di classe.

class DataFetcher {
    abstract Object getData( Object id );

    private static final Map fetchers = new HashMap();static { 
        fetchers.put("customer.name", new CustomerNameDataFetcher() );
        fetchers.put("company.address", new CompanyAdressDataFetcher () );
        fetchers.put("product.color", new ProductColor () );
        ...
    }
    public static DataFetcher getFetcher( String id ) { 
        return fetchers.get( id );
    }      

}

Alla fine per riempire la tabella del front end la chiamo così:

pseudocodice

 for each row in table 
      for each column in row
          column.text = DataFetcher.getFetcher( column.id ).getData( row.id )
       end
 end

È così? O ho letto male la tua descrizione e la mia è abbastanza diversa.

Finalmente penso che questo si chiami SingletonRegistry o qualcosa del genere. (Probabilmente) mi piaci, l'ho creato per necessità. È probabile che questo sia un modello comune.

Altri suggerimenti

Ho usato un modello simile a questo prima, molto spesso nei giochi. Avrei una classe WeaponDefinition e WeaponInstance (non proprio con quei nomi). La classe di definizione dell'arma (e varie sottoclassi, se ho diversi tipi di armi, ad esempio mischia contro proiettile) sarebbe responsabile di tenere traccia dei dati globali per quel tipo di arma (velocità di fuoco, munizioni massime, nome, ecc.) E ha tutta la logica. La classe WeaponInstance (e le sottoclassi) contengono lo stato corrente nella sequenza di sparo (da utilizzare con il confronto della velocità di fuoco), il conteggio delle munizioni corrente e un puntatore (potrebbe essere una chiave in una classe manager come nell'esempio, ma questo non sembra essere un requisito del modello) per la definizione dell'arma. WeaponInstance ha un sacco di funzioni per sparare, ricaricare, ecc., Che chiamano semplicemente il metodo appropriato sull'istanza di WeaponDefinition, passando se stesso come argomento. Ciò significa che le cose di WeaponDefinition non sono duplicate per ogni carro armato / soldato / aeroplano nel mondo di gioco, ma hanno tutti il ??loro numero di munizioni, ecc.

Non ho idea di come si chiama, e non sono sicuro che sia esattamente lo stesso di quello di cui stai parlando, ma penso che sia vicino. È sicuramente utile.

Sembra una combinazione di GoF Builder, Prototype e forse Peso piuma per me.

Sembra una varietà di Flyweight (molte macchine condividono un motore Wankel). Ma che senso ha? La maggior parte delle auto ha un motore, ma come possono molte di loro avere la stessa istanza di un motore? Non andrebbero lontano in quel modo. O vuoi dire che molte macchine hanno un motore di tipo WankelEngine? Spose che ha più senso. Allora a che serve l'oggetto di definizione "WankelEngine"? È una Fabbrica che costruisce sapori di quell'oggetto e li restituisce al richiedente? In tal caso, non suona come un oggetto di definizione, suona più come una Fabbrica che accetta i parametri dell'oggetto per costruire e restituire quell'oggetto.

Vedo alcune buone pratiche GoF qui, in particolare che stai componendo invece di ereditare (la mia auto ha un motore contro il mio motore di macchina è un motore Wankel). Vorrei poter ricordare esattamente la citazione, ma è qualcosa come "l'eredità rompe l'incapsulamento" e "favorire la composizione rispetto all'eredità".

Sono curioso di sapere quale problema sia risolto da questo. Penso che tu abbia aggiunto molta complessità e non vedo la necessità di tale complessità. Forse è qualcosa di specifico per la tua lingua che non capisco.

I ragazzi del GoF discutono di comporre pattern in pattern più grandi, MVC in particolare è un aggregato di altri tre pattern. Sembra che tu abbia fatto qualcosa del genere.

Sembra un po 'come Service Locator, in cui i tuoi pesi piuma sono registrati come singoli.

Quello che hai è una mappa, alias Dizionario. Hai solo una svolta unica, avendo più chiavi mappate su un oggetto.

Perché è una mappa:

  • conserva una chiave
  • Utilizzare la chiave per eseguire una query su un valore da una struttura di dati.

Puoi trovare implementazioni in:

  • STL (include: map)
  • Java (import: java.util.Dictionary)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top