Verwendung des Entwurfsmusters für den Objektpool in C #

Beim Erstellen von Anwendungen stoßen Sie häufig auf Objekte, deren Erstellung recht teuer ist. In einigen Szenarien sind die Kosten für die Erstellung neuer Objekte hoch genug, um die Anwendungsleistung zu beeinträchtigen. Hier kommt das Entwurfsmuster des Objektpools zur Rettung. 

Das Objektpool-Entwurfsmuster ist ein kreatives Entwurfsmuster, das zum Recyceln von Objekten verwendet wird, anstatt sie jedes Mal neu zu erstellen, wenn die Anwendung sie benötigt. Durch die Beibehaltung wiederverwendbarer Instanzen von Objekten in einem Ressourcenpool und deren Verteilung nach Bedarf wird durch diesen Muster der Aufwand für das Initialisieren, Instanziieren und Entsorgen von Objekten minimiert und die Leistung Ihrer Anwendung gesteigert.

Wenn die Anwendung ein Objekt anfordert und das Objekt aus dem Pool verfügbar ist, wird es aus dem Pool zurückgegeben. Wenn das Objekt des angeforderten Typs nicht aus dem Pool verfügbar ist, wird eine neue Instanz des Objekts erstellt und zurückgegeben. Wenn die Anwendung das Objekt nicht mehr benötigt, wird das Objekt an den Pool zurückgesendet.

Die minimale und maximale Anzahl von Objekten, die ein Objektpool enthalten kann, ist konfigurierbar. Wenn die Anwendung ein Objekt aus dem Pool benötigt, aber die maximale Anzahl von Objekten zugewiesen wurde, kann eine typische Implementierung eines benutzerdefinierten Objektpools eine oder mehrere der folgenden Strategien anwenden:

  1. Geben Sie null zurück oder lösen Sie eine Ausnahme aus
  2. Blockieren Sie den Anruf, bis ein Objekt verfügbar ist
  3. Erhöhen Sie die Poolgröße, um mehr Objekte aufzunehmen

Ein Objektpool ähnelt dem Datenbankverbindungspool. So wie der Verbindungspool die maximale Anzahl von Verbindungen zur Datenbank steuert, steuert der Objektpool die Anzahl der Klasseninstanzen, die von der Anwendung verwendet werden.

Erstellen eines generischen Objektpools in C #

Nachdem wir die Grundlagen kennen, können wir mit der Implementierung beginnen. Bei der Implementierung des Entwurfsmusters für den Objektpool müssen Wiederverwendbarkeit, Einfachheit, Konfigurierbarkeit und sogar Faktoren wie die Thread-Sicherheit berücksichtigt werden.

In diesem Beispiel verwenden wir eine ConcurrentBag Klasse zum Speichern von Objekten. Beachten Sie, dass die ConcurrentBagKlasse im System.Collections.ConcurrentNamespace eine sperrfreie, threadsichere und ungeordnete Sammlung von Elementen bereitstellt. Beachten Sie auch, dass das Einfügen und Entfernen von Objekten zu und von a ConcurrentBagsehr schnell ist - insbesondere, wenn derselbe Thread versucht, Elemente gleichzeitig in die Sammlung einzufügen und daraus zu entfernen.

Hier ist die Struktur unserer benutzerdefinierten ObjectPoolKlasse. Beachten Sie die Verwendung der ConcurrentBagInstanz zum Speichern der Objekte.

öffentliche Klasse ObjectPool wobei T: new ()

    {

        private schreibgeschützte ConcurrentBag-Elemente = new ConcurrentBag ();

        privater int Zähler = 0;

        private int MAX = 10;

        public void Release (T-Punkt)

        {

            //MACHEN          

        }}

        public T Get ()

        {

           //MACHEN

        }}

    }}

Das folgende Codefragment veranschaulicht eine Implementierung der GetMethode. Die GetMethode gibt eine Instanz aus dem Objektpool zurück, falls eine verfügbar ist. Wenn keines verfügbar ist, wird ein neues Objekt erstellt und zurückgegeben. In beiden Szenarien wird die counterVariable entsprechend erhöht oder verringert. Beachten Sie, dass, da wir eine gleichzeitige Sammlung verwenden, dh ConcurrentBagin diesem Beispiel die Parallelität berücksichtigt wird.

public T Get ()

        {

            T Artikel;

            if (items.TryTake (out item))

            {

                Zähler-;

                Artikel zurückgeben;

            }}

            sonst

            {

                T obj = neues T ();

                items.Add (obj);

                Zähler ++;

                return obj;

            }}

        }}

Die MAXGanzzahlvariable ist hier fest codiert, Sie können sie jedoch konfigurierbar machen. Diese Klasse ist nicht versiegelt oder statisch, daher können Sie sie beliebig erweitern.

Die ReleaseMethode wird verwendet, um nicht mehr benötigte Objekte wieder in den Objektpool freizugeben. Es prüft, ob der Wert der counterVariablen kleiner als der Wert der MAXVariablen ist, und fügt in diesem Fall das an sie übergebene Objekt als Parameter zur Auflistung hinzu.

public void Release (T-Punkt)

        {

            if (Zähler <MAX)

            {

                items.Add (item);

                Zähler ++;

            }}           

        }}

Angenommen, Sie haben eine Klasse mit dem Namen erstellt MyClass, können Sie sie mithilfe der ObjectPoolKlasse wie folgt zum Objektpool hinzufügen .

statische Leere Main (string [] args)

        {

            ObjectPool objPool = new ObjectPool ();

            MyClass obj = objPool.Get ();

            objPool.Release (obj);

            Console.Read ();

        }}

Sie können diese Implementierung des benutzerdefinierten Objektpools so ändern, dass die minimale und maximale Größe des Pools aus einer Konfigurationsdatei gelesen werden kann. Im Rahmen der Initialisierung des Objektpools können Sie auch sicherstellen, dass der Pool die Mindestanzahl von Objekten enthält.

Objektpools helfen, den Ressourcenaufwand zu reduzieren, wenn Sie mehrere Instanzen einer Klasse benötigen, deren Erstellung oder Verwaltung teuer ist. Wenn in Ihrer Anwendung immer wieder dieselben Klassen instanziiert werden müssen, verwenden Sie dieses Entwurfsmuster, um eine optimale Leistung sicherzustellen.