Как да използвам шаблона за проектиране на обектния пул в C #

Когато изграждате приложения, често срещате обекти, които са доста скъпи за създаване. В някои сценарии разходите за създаване на нови обекти са достатъчно високи, за да повлияят на производителността на приложението. Тук на помощ идва моделът на проектиране на обектния басейн. 

Шаблонът за проектиране на обектен пул е творчески модел на дизайн, който се използва за рециклиране на обекти, вместо да ги пресъздава всеки път, когато приложението се нуждае от тях. Като съхранява повторно използваеми екземпляри на обекти в пула ресурси и ги разпределя при необходимост, този модел помага да се сведе до минимум режийните разходи за инициализиране, инстанциране и изхвърляне на обекти и за повишаване на производителността на вашето приложение.

Когато приложението поиска обект и обектът е наличен от пула, той се връща от пула. Ако обектът от искания тип не е наличен от пула, тогава се създава и връща нов екземпляр на обекта. Когато приложението вече не се нуждае от обекта, обектът се изпраща обратно в пула.

Минималният и максималният брой обекти, които обектният пул може да побере, е конфигурируем. Ако приложението се нуждае от обект от пула, но е разпределен максималният брой обекти, типично изпълнение на обект от потребителски пул може да възприеме една или повече от следните стратегии:

  1. Връща null или изхвърля изключение
  2. Блокирайте повикването, докато има наличен обект
  3. Увеличете размера на басейна, за да поберете повече обекти

Обектният пул е подобен на пула за връзка с база данни. Точно както пулът от връзки контролира максималния брой връзки към базата данни, обектният пул контролира броя на екземплярите на класа, които приложението ще използва.

Създаване на общ пул от обекти в C #

След като вече знаем основите, нека да преминем към изпълнението. Когато прилагаме шаблона за проектиране на обектния пул, трябва да вземем предвид повторната употреба, простотата, конфигурируемостта и дори фактори като безопасността на нишките.

В този пример ще се възползваме от ConcurrentBag клас за съхраняване на обекти. Обърнете внимание, че ConcurrentBagкласът в System.Collections.Concurrentпространството на имената осигурява без заключване, обезопасена с нишки, неподредена колекция от елементи. Също така имайте предвид, че вмъкването и премахването на обекти от и до ConcurrentBagе много бързо - особено ако същата нишка се опитва да вмъква и премахва елементи от колекцията едновременно.

Ето структурата на нашия потребителски ObjectPoolклас. Обърнете внимание на използването на ConcurrentBagекземпляра за съхраняване на обектите.

публичен клас ObjectPool където T: new ()

    {

        частни елементи за четене ConcurrentBag = нов ConcurrentBag ();

        частен брояч int = 0;

        private int MAX = 10;

        Публично освобождаване (T артикул)

        {

            //ДА НАПРАВЯ          

        }

        публично T Вземете ()

        {

           //ДА НАПРАВЯ

        }

    }

Следният кодов фрагмент илюстрира изпълнение на Getметода. В Getметода се връща екземпляр от обект басейна, ако има такъв. Ако няма наличен, се създава и връща нов обект. И в двата сценария counterпроменливата се увеличава или намалява според случая. Имайте предвид, че тъй като използваме едновременна колекция, т.е. ConcurrentBagв този пример се грижи за едновременността.

публично T Вземете ()

        {

            Т артикул;

            if (items.TryTake (out item))

            {

                брояч—;

                Върни предмета;

            }

            друго

            {

                T obj = ново T ();

                items.Add (obj);

                брояч ++;

                return obj;

            }

        }

В MAXпроменливата число е твърдо кодирана тук, но можете да го направите конфигурируеми. Този клас не е запечатан или статичен, така че можете да го разширите, както искате.

В Releaseметода се използва за освобождаване на обекти, които вече не са необходими обратно към обект басейна. Той проверява дали стойността на counterпроменливата е по-малка от стойността на MAXпроменливата и ако е така, добавя обекта, предаден към нея като параметър към колекцията.

Публично освобождаване (T артикул)

        {

            ако (брояч <MAX)

            {

                items.Add (артикул);

                брояч ++;

            }           

        }

Ако приемем, че сте създали клас, наречен MyClass, ето как можете да го добавите към обектния пул с помощта на ObjectPoolкласа.

static void Main (низ [] аргументи)

        {

            ObjectPool objPool = нов ObjectPool ();

            MyClass obj = objPool.Get ();

            objPool.Release (obj);

            Console.Read ();

        }

Можете да модифицирате тази реализация на персонализиран обект, за да позволите минималните и максималните размери на пула да бъдат прочетени от конфигурационен файл. Като част от инициализацията на обектния пул, можете също така да гарантирате, че пулът съдържа минималния брой обекти в него.

Пуловете на обекти помагат за намаляване на режийните разходи, когато имате нужда от множество екземпляри на клас, които са скъпи за създаване или управление. Ако вашето приложение включва инстанциране на едни и същи класове отново и отново, използвайте този модел на проектиране, за да осигурите оптимална производителност.