Come usare il modello di progettazione del pool di oggetti in C #

Quando si creano applicazioni, spesso ci si imbatte in oggetti piuttosto costosi da creare. In alcuni scenari, il costo della creazione di nuovi oggetti è sufficientemente elevato da influire sulle prestazioni dell'applicazione. È qui che viene in soccorso il modello di progettazione del pool di oggetti. 

Il modello di progettazione del pool di oggetti è un modello di progettazione creazionale che viene utilizzato per riciclare gli oggetti anziché ricrearli ogni volta che l'applicazione ne ha bisogno. Mantenendo istanze riutilizzabili di oggetti in un pool di risorse e distribuendole secondo necessità, questo modello aiuta a ridurre al minimo il sovraccarico di inizializzazione, istanziazione ed eliminazione degli oggetti e ad aumentare le prestazioni dell'applicazione.

Quando l'applicazione richiede un oggetto e l'oggetto è disponibile dal pool, viene restituito dal pool. Se l'oggetto del tipo richiesto non è disponibile dal pool, viene creata e restituita una nuova istanza dell'oggetto. Quando l'applicazione non necessita più dell'oggetto, l'oggetto viene rimandato al pool.

Il numero minimo e massimo di oggetti che un pool di oggetti può contenere è configurabile. Se l'applicazione richiede un oggetto dal pool ma è stato allocato il numero massimo di oggetti, un'implementazione tipica di un pool di oggetti personalizzato può adottare una o più delle seguenti strategie:

  1. Restituisce null o genera un'eccezione
  2. Blocca la chiamata finché un oggetto non è disponibile
  3. Aumenta le dimensioni della piscina per accogliere più oggetti

Un pool di oggetti è simile al pool di connessione del database. Proprio come il pool di connessioni controlla il numero massimo di connessioni al database, il pool di oggetti controlla il numero di istanze di classe che verranno utilizzate dall'applicazione.

Creazione di un pool di oggetti generico in C #

Ora che conosciamo le basi, passiamo all'implementazione. Quando si implementa il modello di progettazione del pool di oggetti, è necessario considerare la riusabilità, la semplicità, la configurabilità e persino fattori come la sicurezza dei thread.

In questo esempio trarremo vantaggio da una ConcurrentBag classe per memorizzare gli oggetti. Si noti che la ConcurrentBagclasse nello System.Collections.Concurrentspazio dei nomi fornisce una raccolta di elementi priva di blocchi, thread-safe e non ordinati. Si noti inoltre che l'inserimento e la rimozione di oggetti da e verso a ConcurrentBagè molto veloce, specialmente se lo stesso thread sta cercando di inserire e rimuovere elementi dalla raccolta contemporaneamente.

Ecco la struttura della nostra ObjectPoolclasse personalizzata . Notare l'utilizzo ConcurrentBagdell'istanza per memorizzare gli oggetti.

Classe pubblica ObjectPool dove T: new ()

    {

        elementi ConcurrentBag di sola lettura privati ​​= new ConcurrentBag ();

        contatore int privato = 0;

        int privato MAX = 10;

        public void Release (elemento T)

        {

            //FARE          

        }

        public T Get ()

        {

           //FARE

        }

    }

Il frammento di codice seguente illustra un'implementazione del Getmetodo. Il Getmetodo restituisce un'istanza dal pool di oggetti, se disponibile. Se nessuno è disponibile, viene creato e restituito un nuovo oggetto. In entrambi questi scenari, la countervariabile viene aumentata o diminuita a seconda dei casi. Si noti che poiché stiamo utilizzando una raccolta simultanea, ovvero, ConcurrentBagin questo esempio, la concorrenza viene presa in considerazione.

public T Get ()

        {

            Articolo T;

            if (items.TryTake (out item))

            {

                counter—;

                articolo di ritorno;

            }

            altro

            {

                T obj = nuovo T ();

                items.Add (obj);

                counter ++;

                return obj;

            }

        }

La MAXvariabile intera è hardcoded qui, ma puoi renderla configurabile. Questa classe non è sigillata o statica, quindi puoi estenderla a tuo piacimento.

Il Releasemetodo viene utilizzato per rilasciare oggetti che non sono più necessari nel pool di oggetti. Verifica se il valore della countervariabile è inferiore al valore della MAXvariabile e, in tal caso, aggiunge l'oggetto passato come parametro alla raccolta.

public void Release (elemento T)

        {

            if (contatore <MAX)

            {

                elementi. Aggiungi (elemento);

                counter ++;

            }           

        }

Supponendo che tu abbia creato una classe chiamata MyClass, ecco come puoi aggiungerla al pool di oggetti usando la ObjectPoolclasse.

static void Main (string [] args)

        {

            ObjectPool objPool = new ObjectPool ();

            MyClass obj = objPool.Get ();

            objPool.Release (obj);

            Console.Read ();

        }

È possibile modificare questa implementazione del pool di oggetti personalizzato per consentire la lettura delle dimensioni minime e massime del pool da un file di configurazione. Come parte dell'inizializzazione del pool di oggetti, puoi anche assicurarti che il pool contenga il numero minimo di oggetti al suo interno.

I pool di oggetti aiutano a ridurre il sovraccarico delle risorse quando sono necessarie più istanze di una classe costose da creare o gestire. Se l'applicazione prevede la creazione ripetuta di istanze delle stesse classi, utilizzare questo modello di progettazione per garantire prestazioni ottimali.