Qualcuno ha un esempio specifico di utilizzo del modello Flyweight? [chiuso]


21

Ho studiato modelli di progettazione e mi sono imbattuto nel modello del peso mosca. Ho cercato di vedere le opportunità di utilizzare il modello nelle mie applicazioni, ma ho difficoltà a vedere come usarlo. Inoltre, quali sono alcuni segni che viene utilizzato un modello di peso mosca quando leggo il codice di altre persone?

Secondo la definizione si dice:

Utilizzare la condivisione per supportare in modo efficiente un gran numero di oggetti a grana fine.

Se la leggessi bene, i dizionari e gli hashtable potrebbero essere esempi di pesi volanti, è corretto?

Grazie in anticipo.


7
Solo un piccolo aneddoto sui pesi mosca: una volta ho dovuto creare file Excel di grandi dimensioni (fino a 500.000 record, oltre 100 colonne) con un'API di terze parti. Gli stili per le celle sono diventati estremamente intensi di memoria. Quindi ogni volta che era necessario uno stile, veniva controllata una tabella hash se esisteva già uno stile uguale e quindi fornito solo un riferimento a questo stile. Questa modifica ha reso possibile questa esportazione. Ora avere così tanti dati in Excel è una follia secondo me. Ma i controller avevano le loro macro di analisi che volevano mantenere.
Falcon,

9
Commento: spero che le persone che scrivono modelli e libri e articoli OO vengano nel mondo reale del programmatore medio e smettano di usare l'inglese in stile avvocato!
NoChance,

1
"Una volta ho dovuto creare grandi file Excel (fino a 500k record, oltre 100 colonne)" - non molto rispetto a ciò che alcuni trader sono in grado di creare ;-)
quant_dev

Dopo aver letto alcuni di questi esempi, penso che la compressione dei dati in memoria sarebbe un posto eccellente per implementare questa tecnica. Grazie per l'aiuto!
Jeremy E

Le celle della tabella in GWT sono pesi volanti.
user16764

Risposte:


19

Un esempio è nelle librerie Java. Java ha tipi primitivi (ad es. int, Che è un numero intero a 32 bit) e wrapper per essi (ad es Integer. Che avvolge int). Esistono metodi per "box" an intin an Integere unbox an Integerin an int. I wrapper sono necessari perché i tipi primitivi non sono oggetti e quindi non possono ad esempio essere usati come chiavi in Maps o inseriti in Collections.

Il metodo di inscatolamento utilizza una matrice di oggetti flyweight come una specie di cache per Integers corrispondenti a intvalori compresi tra -128 e 127. Poiché questi sono i valori che più probabilmente verranno utilizzati come chiavi o inseriti in raccolte, riduce l'allocazione e l'uso della memoria. (Se ci sono 5000000 Integers che rappresentano il valore 0 fluttuante, che utilizza 5000000 volte più memoria del riutilizzo dell'istanza flyweight).



1
Quindi il pool di stagisti per stringhe in C # è un altro esempio del modello flyweight corretto?
Jeremy E,

1
@Jeremy E: Sì, secondo me puoi chiamare lo string interning in un'applicazione del modello flyweight, anche se per stringhe, non riguarda solo il consumo di memoria, ma anche l'efficienza di runtime.
Falcon,

I puntatori con tag Objective-C lo portano all'estremo. Interi inscatolati fino a 56 bit e molte stringhe fino a sei caratteri, non vengono nemmeno allocati come oggetti, ma tutte le informazioni vengono impacchettate nel puntatore dell'oggetto stesso.
gnasher729,

9

Grafica. In genere, un'immagine raster (che è la spina dorsale della maggior parte dei computer grafica a livello di consumatore) è economica per la CPU, ma è costosa da utilizzare con la memoria (il che va bene perché la memoria è economica ma la CPU è costosa). Se l'immagine raster deve essere ripetuta più volte nel rendering di un'interfaccia utente più grande (dalle icone in un'app GUI di Windows ai caratteri di un font in un elaboratore di testi, alle trame sulle superfici in un gioco 3D), ha molto senso caricare l'immagine in memoria una volta e puntare semplicemente su di essa usando oggetti molto semplici che sono economici da realizzare e non occupano essi stessi molta memoria. Uno sprite, che è semplicemente un punto nello spazio grafico in cui un'immagine deve essere visualizzata, è solo un punto 3D e un puntatore di memoria al primo pixel dell'immagine da usare. FORSE include anche le dimensioni della porzione del file immagine sprite da utilizzare, in termini grafici o di memoria. Queste informazioni sono tutte molto economiche per cambiare, diciamo per cambiare l'immagine o la posizione dello sprite, e possono essere fatte senza caricare una nuova immagine ogni volta, aumentando così drasticamente le prestazioni del programma sottostante per manipolare e visualizzare le porzioni appropriate del immagini appropriate per il rendering di una "scena" dell'interfaccia utente completa.


3

Le Characteristanze dell'intervallo ASCII in Smalltalk sono pesi mosca.

Quando valuti qualcosa del genere Character space, Character class >> #value:esegue:

value: anInteger 
    "Answer the Character whose value is anInteger."

    anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
    ^ CharacterTable at: anInteger + 1.

La variabile di classe CharacterTableviene inizializzata in questo modo:

initialize
    "Create the table of unique Characters, and DigitsValues."
    "Character initializeClassificationTable"

    CharacterTable ifNil: [
        "Initialize only once to ensure that byte characters are unique"
        CharacterTable := Array new: 256.
        1 to: 256 do: [:i | CharacterTable
            at: i
            put: (self basicNew setValue: i - 1)]].
    self initializeDigitValues

Quindi, quando crei una stringa, la gamma ASCII Characterverrà CharacterTableinvece che essere appena creata ogni volta.


3

Lo scopo dell'uso del modello flyweight è quello di evitare un'inizializzazione degli oggetti non necessaria e quindi risparmiare spazio. Come definito da GOF , un oggetto può avere due stati, lo stato intrinseco e quello estrinseco:

  • Stato intrinseco: è immagazzinato nel peso mosca; è costituito da informazioni indipendenti dal contesto dei pesi mosca, rendendole condivisibili.
  • Stato estrinseco: dipende e varia a seconda del contesto del peso mosca e quindi non può essere condiviso. Gli oggetti client sono responsabili del passaggio dello stato estrinseco al peso mosca quando ne ha bisogno.

Supponendo che vogliamo sviluppare una semplice applicazione di editor di testo in cui ogni colonna contenga tutte le righe del testo e la riga possa contenere caratteri.

Il dilemma qui è come progettare la classe Character. Il char call'interno della classe personaggio dovrebbe essere il principale (stato intrinseca) dell'oggetto. Tuttavia, un carattere può avere un carattere e una dimensione (stato estrinseco); quindi abbiamo bisogno di memorizzare il suo stato estrinseco sulla riga (client) e accedervi quando necessario. A tale scopo, vengono creati due elenchi che memorizzano i caratteri e le dimensioni.

Seguendo il modello Flyweight, il personaggio è ora riutilizzabile e agli oggetti viene fatto riferimento da un elenco specifico di oggetti (il pool flyweight) che contiene tutti i simboli ASCII ( Characteroggetti).

Ecco cosa ho descritto visivamente:

inserisci qui la descrizione dell'immagine

Per stampare 'ciao', Charactersono necessari solo 4 oggetti, anziché 5. Una volta modificato il carattere, non sono necessari nuovi oggetti; nota che ciò non sarebbe possibile se avessimo memorizzato lo stato estrinseco nella classe Character, ad es.

class Character
{
    char c;
    int Size;
    Font font;

    ....
}

L'applicazione di questo modello su set di dati di grandi dimensioni porterebbe a ottimizzazioni significative sulla complessità della memoria dell'applicazione e sulla riusabilità degli oggetti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.