Օբյեկտների ավազան (նախագծման ձևանմուշ)

Օբյեկտների ավազանը ծրագրային ապահովման ստեղծող ձևանմուշ է, որն ինիցալիազացված օբյեկտներն ըստ պահանջի չի վերացնում, այլ դրանք պահում է «ավազանում»՝ պատրաստ հետագա օգտագործման համար։ Հայցողը ավազանից հայցում է օբյեկտը և վերադարձված օբյեկտի նկատմամբ իրագործում է անհրաժեշտ գործողությունները։ Երբ հայցողն իր աշխատանքն ավարտում է, օբյեկտը չի ոչնչացվում, այլ վերադարձվում է ավազան։

Օբյեկտների ավազան
ՏեսակՍտեղծող
ՆշանակությունԻնիցիալիզացված օբյեկտները հետագա օգտագործման համար պահում է ավազանում
ԿիրառությունԾրագրի արդյունավետության բարձրացման համար
ԱռավելություններԲարձրացնում է ծրագրային ապահովվածության արդյունավետությունը
ԹերություններԲարդ է հաշվարկել օբյեկտների կյանքի տևողությունը
Նկարագրությունը ԳօՖի
"Design Patterns" գրքում
Չկա

Օբյեկտների ավազաններն հիմնականում օգտագործում են ծրագրի էֆեկտիվության նպատակով։ Որոշ դեպքերում, այն զգալիորեն բարձրացնում է ծրագրի աշխատանքի էֆեկտիվությունը։ Օբյկետների կյանքի տևողությունն այս դեպքում հաշվելը բարդ է, քանի որ օբյեկտները իրականում չեն ստեղծվում և ոչնչացվում, այլ վերցվում են ավազանից և այնտեղ էլ վերադարձվում։

Ընդհանուր հասկացողություններ խմբագրել

  • Client - հայցող
  • Instance - նմուշ
  • Implementation - իրականացում
  • Product - արգասիք

Նկարագրություն խմբագրել

Ծրարգրի աշխատանքի արդյունավետությունը շատ ցածր կլինի, եթե ծրագրին անհրաժեշտ է աշխատել մեծ քանակի օբյեկտների հետո, որոնց նմուշների ստեղծումը աշխատատար է և նմուշներն էլ իրենց հերթին շատ կարճ ժամանակահատվածում են անհրաժեշտ։ Այս դեպքերի համար էլ ցանկալի է կիրառել օբյեկտների ավազանը։

Օբյեկտների ավազան նախագծման ձևանմուշը ստեղծում է օբյեկտների բազմություն, որոնք կարող են վերաօգտագործվել։ Երբ նոր օբյեկտ է անհրաժեշտ լինում, այն վերցվում է ավազանից։ Եթե անհրաժեշտ օբյեկտն արդեն գոյություն ունի, այն անմիջապես վերադարձվում է, որի արդյունքում էլ խուսափում ենք նմուշի ստեղծման վրա ծախսվող ժամանակից։ Եթե օբյեկտը չկա ավազանում, ապա այն ստեղծվում է և վերադարձվում։ Երբ օբյեկտն օգտագործվել է և այլևս անհրաժեշտ չէ, այն կրկին վերադարձվում է ավազան հետագա օգտագործման և ստեղծման ժամանակի խնայման նպատակով։ Հատկանշական է նշել, որ երբ նմուշը օգտագործվում և վերադարձվում է, գոյություն ունեցող հղումները դառնում են չգործող (անգլ.՝ invalid

Որոշ ավազանների մոտ օբյեկտների ռեսուրսները սահմանափակ են, դրա համար էլ տրվում է մաքսիմում օբյեկտների քանակը։ Եթե հայցվող օբյեկտների թիվը հասնում է մաքսիմումին, ծրագիրը կարող է exception գցի, կամ հոսքը անգլ.՝ thread կբլոկավորվի, մինչև նախկին օբյեկտներից մեկը ավազան վերադառնա։

Օբյեկտների ավազան նախագծման ձևանմուշը մի քանի տեղ օգտագործվում է .NET framework-ի ստանդարտ դասերում։ Նմանատիպ օրինակ է հանդիսանում .NET Framework-ի SQL ServerData Provider-ը։ Այստեղ օբյեկտների ավազանն օգտագործվում է, քանի որ SQL Server-ի տվյալների բազայի հետ կապը կարող է դանդաղ լինել։ SQL Server-ի կապի փակման դեպքում իրականում կապը դեպի հղվող օբյեկտ չի վերանում։ Դրա փոխարեն կապը տեղափոխվում է ավազան և հաջորդ կանչի ժամանակ այն դուրս է բերվում ավազանից։ Այս մեթոդն էապես արագացնում է կապի արագությունը։

Առավելություններ խմբագրել

Օբյեկտների ավազանի շնորհիվ կարելի է զգալիորեն բարձրացնել արտադրողականությունը, երբ դասի նմուշի ինիցիալիզացիան կամ նրա վերացումը ժամանակատար են։ Այս դեպքում օբյեկտները հաճախակի մտնում են վերաշրջանառման մեջ և նրանցից ամեն մեկն էապես կտնտեսի ռեսուրսների հատկացման կամ վերացման վրա ծախսվող ժամանակը։ Օբյեկտների ավազանը ռեսուրսներ է պահանջում, որպիսիք են օրինակ հիշողությունը, որոշ դեպքերում ցանցային սոկետները անգլ.՝ network socket: Այդ առումով լավ կլինի ունենալ մինիմալ քանակությամբ օգտագործվող ձևանմուշներ։ Սակայն վերջինս պարտադիր պայման չի հանդիսանում։

Օբյեկտների ավազանն հասնում է կանխատեսելի ժամանակին, երբ նոր օբյեկտների (հատկապես ցանցային) ստեղծման ժամանակը դառնում է փոփոխական։ Այս առավելությունն հիմնականում վերաբերվում է այն օբյեկտներին, որոնց ստեղծումը ժամանակատար է՝ հատկապես տվայալների բազաների, սոկետների միացումներին, հոսքերին (անգլ.՝ thread) և մեծ գրաֆիկական օբյեկտների համար՝ ինչպիսիք են օրինակ շրիֆտները և ռաստրային պատկերները։

Պարզ օբյեկտների օգտագործումը ավազաններում, որոնք օրինակ ստեղծման համար ժամանակատար չեն, այլ լոկ հիշողության ռեսուրս են խլում, էֆեկտիվ չէ, քանի որ այն կարող է բերել արտադրողականության իջեցմանը[1]։ Այս դեպքում ավելի նպատակահարմար է օգտագործել հիշողության ավազանը, որի խնդիրն է հիշողության ծախսերը բերել մինիմումի կամ ազատել։

Իրականացում խմբագրել

Օբյեկտների ավազանը կարող է իրականացվել ձեռքով՝ ֆաբրիկայից օբյեկտի բացահայտ հայցման և օբյեկտի վերադարձը կարգավորող ձևանմուշի (անգլ.՝ dispose pattern) օգնությամբ։ Բացի այդ, աղբ-հավաքող լեզուներում, օբյեկտների ավազանը դասի համար կարող է իրականացվել ավտոմատ կերպով[2]։

Օրինակ C# լեզվով խմբագրել

.NET-ի Base Class Library-ում կան մի քանի օբյեկտներ, որոնք իրականացված են այս ձևանմուշով։ System.Threading.ThreadPool-ն այնպես է կոնֆիգուրացված, որպեսզի բաշխումն իրականացնելու համար ունենա կոնկրետ հոսքերի անգլ.՝ thread քանակ։ Երբ հոսքերը վերադարձվեն, նրանք կկարողանան այլ աշխատանքներ կատարել։ Այսպիսով կարելի է օգտագործել հոսքերը՝ նրանց ստեղծման և ջնջման վրա ռեսուրս չծախսելով։

Ներքևում C # լեզվով բերված է օբյեկտների ավազան ձևանմուշի իրականացումը։ Կարճության համար դասի հատկանիշները անգլ.՝ property հայտարարվել են C# 3.0 automatically implemented property syntax-ի միջոցով։ Լեզվի հին տարբերակների համար դրանք պետք է փոխարինել լրիվ իրականցման կոդերով։

Ավազանն այստեղ ցույց է տրված ստատիկ դասի տեսքով, ինչքան էլ որ այն անսովոր լինի բազմաթիվ ավազանների համար։

//IVSR: ObjectPool Design pattern
namespace IVSR.DesignPatern.Objectpool 
{
/* The PooledObject class is the type that is expensive or slow to instantiate, or that has limited availability, so is to be held in the object pool. */
public class PooledObject
{
    DateTime _createdAt = DateTime.Now;
 
    public DateTime CreatedAt
    {
        get { return _createdAt; }
    }
 
    public string TempData { get; set; }
}

/* The Pool class is the most important class in the object pool design pattern. It controls access to the
pooled objects, maintaining a list of available objects and a collection of objects that have already been
requested from the pool and are still in use. The pool also ensures that objects that have been released
are returned to a suitable state, ready for the next time they are requested. */ 
public static class Pool
{
    private static List<PooledObject> _available = new List<PooledObject>();
    private static List<PooledObject> _inUse = new List<PooledObject>();
 
    public static PooledObject GetObject()
    {
        lock(_available)
        {
            if (_available.Count != 0)
            {
                PooledObject po = _available[0];
                _inUse.Add(po);
                _available.RemoveAt(0);
                return po;
            }
            else
            {
                PooledObject po = new PooledObject();
                _inUse.Add(po);
                return po;
            }
        }
    }
 
    public static void ReleaseObject(PooledObject po)
    {
        CleanUp(po);
 
        lock (_available)
        {
            _available.Add(po);
            _inUse.Remove(po);
        }
    }
 
    private static void CleanUp(PooledObject po)
    {
        po.TempData = null;
    }
}
}

Բերված ծրագրային կոդում PooledObject-ն իր մեջ երկու հատկություն է ներառում, որը չի պատկերված UML դիագրամայում։ Առաջինը դա օբեյկտի առաջին անգամվա ստեղծման ժամանակն է։ Երկրորդը տվյալ է պահում, որը կարող է փոփոխվել հայցողի կողմից, երբ PooledObject օբյեկտը վերադարձվում է ավազան։ Իրականում այդ դաշտը տվյալ է պահում, որ օբյեկտը ազատ է, թե՝ ոչ, որը պետք է գալիս օբյեկտի հայցման ժամանակ։

Ծանոթագրություններ խմբագրել

  1. Goetz, Brian (2005 թ․ սեպտեմբերի 27). «Java theory and practice: Urban performance legends, revisited». IBM developerWorks. Արխիվացված է օրիգինալից 2013 թ․ հոկտեմբերի 24-ին. Վերցված է 2012 թ․ օգոստոսի 28-ին.
  2. Goldshtein, Zurbalev, էջ 129