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:
- Geben Sie null zurück oder lösen Sie eine Ausnahme aus
- Blockieren Sie den Anruf, bis ein Objekt verfügbar ist
- 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 ConcurrentBag
Klasse im System.Collections.Concurrent
Namespace eine sperrfreie, threadsichere und ungeordnete Sammlung von Elementen bereitstellt. Beachten Sie auch, dass das Einfügen und Entfernen von Objekten zu und von a ConcurrentBag
sehr schnell ist - insbesondere, wenn derselbe Thread versucht, Elemente gleichzeitig in die Sammlung einzufügen und daraus zu entfernen.
Hier ist die Struktur unserer benutzerdefinierten ObjectPool
Klasse. Beachten Sie die Verwendung der ConcurrentBag
Instanz 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 Get
Methode. Die Get
Methode 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 counter
Variable entsprechend erhöht oder verringert. Beachten Sie, dass, da wir eine gleichzeitige Sammlung verwenden, dh ConcurrentBag
in 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 MAX
Ganzzahlvariable 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 Release
Methode wird verwendet, um nicht mehr benötigte Objekte wieder in den Objektpool freizugeben. Es prüft, ob der Wert der counter
Variablen kleiner als der Wert der MAX
Variablen 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 ObjectPool
Klasse 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.