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

20

Ho studiato i modelli di progettazione e sono arrivato attraverso il modello del peso della mosca. Ho cercato di vedere le opportunità per utilizzare il modello nelle mie applicazioni, ma ho difficoltà a vedere come usarlo. Inoltre, quali sono alcuni segni che un modello di peso della mosca viene utilizzato quando leggo il codice di altri popoli?

Secondo la definizione dice:

Use sharing to support large numbers of fine-grained objects efficiently.

Se ho letto bene Dizionari e Hashtables potrebbero essere esempi di pesi mosca è corretto?

Grazie in anticipo.

    
posta Jeremy E 15.09.2011 - 22:36
fonte

4 risposte

17

Un esempio è nelle librerie Java. Java ha tipi primitivi (ad esempio int , che è un numero intero a 32 bit) e wrapper per essi (ad esempio Integer , che include int ). Esistono metodi per "inscatolare" un int in Integer e unbox un Integer in int . I wrapper sono necessari perché i tipi primitivi non sono oggetti e quindi non possono, ad es. essere utilizzato come chiave in Map s o inserito in Collection s.

Il metodo di boxe utilizza una serie di oggetti flyweight come un tipo di cache per Integer s corrispondente a int valori tra -128 e 127. Poiché questi sono i valori che più probabilmente saranno usati come chiavi o inseriti nelle raccolte , riduce l'allocazione e l'uso della memoria. (Se ci sono il 5000000% diInteger s che rappresenta il valore 0 fluttuante, che usa 5000000 volte la stessa quantità di riutilizzo dell'istanza del peso mosca).

    
risposta data 15.09.2011 - 22:44
fonte
8

Grafica. In genere, un'immagine raster (che costituisce la spina dorsale della maggior parte della grafica per computer di livello consumer) è a basso costo per CPU, ma è costosa per 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 di un'app GUI di Windows ai caratteri di un font in un word processor, alle trame sulle superfici in un gioco 3D), ha molto senso carica l'immagine in memoria una volta, e semplicemente puntala ad essa usando oggetti molto semplici che sono poco costosi da fare e, di per sé, occupano molta memoria. Uno sprite, che è semplicemente un punto nello spazio grafico in cui deve essere visualizzata un'immagine, è solo un punto 3D e un puntatore di memoria al primo pixel dell'immagine da usare. FORSE comprende anche le dimensioni della porzione del file immagine sprite da utilizzare, sia in termini grafici che di memoria. Queste informazioni sono tutte molto economiche da cambiare, ad esempio 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 parti appropriate del immagini corrette per rendere una "scena" dell'interfaccia utente completa.

    
risposta data 16.09.2011 - 00:18
fonte
3

Le istanze Character di intervallo ASCII in Smalltalk sono di tipo flyweights.

Quando valuti qualcosa come 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 CharacterTable viene 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, il% ASCII dell'intervallo Character verrà da CharacterTable anziché essere ogni volta creato di nuovo.

    
risposta data 15.09.2011 - 23:11
fonte
3

Lo scopo dell'utilizzo del modello del peso mosca è quello di evitare un'inizializzazione non necessaria dell'oggetto e quindi di risparmiare spazio. Come definito da GOF , un oggetto può avere due stati, quello intrinseco e quello estrinseco:

  • Intrinsic state: Is stored in the flyweight; it consists of information that's independent on the flyweights context, thereby making it shareable.
  • Extrinsic state: depends on and varies with the flyweight's context and therefore cant be share. Client objects are responsible for passing extrinsic state to the flyweight when it needs it.

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

Il dilemma qui è come progettare la classe di caratteri. Il char c all'interno della classe Carattere dovrebbe essere l'oggetto principale (stato intrinseco). Tuttavia, un char può avere un font 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 tipi di carattere e le dimensioni.

Seguendo il modello di peso mosca, il personaggio è ora riutilizzabile e gli oggetti vengono referenziati da un elenco specifico di oggetti (il pool del peso corporeo) che contiene tutti i simboli ASCII (% oggetti% co_de).

Ecco ciò che ho descritto visivamente:

Per stampare 'ciao', sono necessari solo il 4% di oggettiCharacter, invece di 5. Una volta cambiato il carattere, non sono richiesti nuovi oggetti; nota che questo non sarebbe possibile se avessimo memorizzato lo stato estrinseco nella classe Character, ad esempio,

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

    ....
}

Applicare questo modello su serie di dati di grandi dimensioni porterebbe a significative ottimizzazioni sulla complessità della memoria dell'applicazione e alla riusabilità dell'oggetto.

    
risposta data 12.04.2017 - 18:34
fonte

Leggi altre domande sui tag