این سایت برای ie9 طراحی نشده است

لطفا دستگاه خود را بچرخانید.

الگوی طراحی – Iterator

۲۰ اردیبهشت ۱۳۹۶ حسین صداقت
بدون دیدگاه

به نام خدا

همانطور که در مطلب قبل اشاره کردیم در این مطلب می خواهیم الگوی طراحی Iterator را با هم بررسی کنیم.

در همه زبان های برنامه نویسی داشتن مجموعه  و لیستی از اشیا  (Collection)  اتفاقی است که بسیار رخ میده.زمانی هم که ما یک مجموعه ای از اشیا داریم پیمایش این مجموعه برای دسترسی به اشیا یکی از مسائلی هستش که ما با آن  رو به رو می شیم. در اکثر زبان های برنامه نویسی تکنیک هایی برای پیمایش انواع Collection وجود دارد. (در زبان برنامه نویسی C# List و ArrayList دو نوع Collection می باشند)

فرض کنید ما یکCollection  داریم که می خواهیم که آن را به وسیله یک حلقه for پیمایش کنیم.این پیمایش به صورت زیر می شود (مثالی که می زنیم برای زبان C# می باشد ولی در اکثر زبان های برنامه نوسی این قضیه مشابه است):

List<string> collection = new List<string>();
            collection.Add("1");
            collection.Add("2");
            collection.Add("3");
            collection.Add("4");
            collection.Add("5");
            for (int i = 0; i < collection.Count; i++)
            {
                var b = collection[i];
            }

 

در این نوع پیمایش ما باید حواسمان به این قضیه باشد که :

۱-باید شروع index ی که خانه های Collection ها ما از آنجا پر شده است را در نظر داشته باشیم.

۲- باید Index فعلی رو نگه داریم که در اینجا متغیر این کار رو برای ما می کنه.

۳- پیمایش باید تا جایی ادامه پیدا کنه که Collection ما پر شده و اگر پیمایش از سایز Collection ما بیشتر بشه ما با خطا رو به رو میشیم.

ما باید ۳ مورد بالا رو در پیمایش بالا مد نظر قرار بدیم.

حالا سراغ الگوی طراحی Iterator می رویم.  این Design Pattern در حقیقت منطق پیمایش یک Collection رو از خود شئ Collection جدا میکند.یعنی ما رو از درگیری با ۳ مورد بالا که در یک پیمایش معمولی با آن رو به رو هستیم راحت می کند.

نمودار UML کلاس آن به صورت زیر است:

Iterator

نقش ها و کلاس های شرکت کننده در این Design Pattern  موارد زیر هستند:

Iterator : یک اینترفیس برای دسترسی و پیمایش خانه های آرایه

ConcreteIterator : اینترفیس Iterator را پیاده سازی می کند

Aggregate : یک اینترفیس برای ایجاد شئ تکرار شونده

ConcreteAggregate : اینترفیس Aggregate را پیاده سازی می کند.در حقیقت Collection واقعی ما در این کلاس قرار می گیرد.

 

حال به سراغ مثال برویم:

 

اینترفیس IIterator را در نظر بگیرید:

interface IIterator
{
    string FirstItem { get;}
    string NextItem{ get;}
    string CurrentItem{ get;}
    bool IsDone { get;}
}

 

اینترفیس بعدی IAggregate می باشد:

interface IAggregate
{
    IIterator GetIterator();
    string this[int itemIndex]{set;get;}
    int Count{get;}
}

 

این اینترفیس را کلاس MyAggregate پیاده سازی می کند.

حال به سراغ پیاده سازی کلاس MyAggregateمی رویم:

class MyAggregate : IAggregate
{
    List<string> values_ = null;

    public MyAggregate()
    {
        values_ = new List<string>();
    }

    #region IAggregate Members

    public IIterator GetIterator()
    {
        return new MyIterator(this);
    }

    #endregion

    public string this[int itemIndex]
    {
        get
        {
            if (itemIndex < values_.Count)
            {
                return values_[itemIndex];
            }
            else
            {
                return string.Empty;
            }
        }
        set
        {                
            values_.Add(value);                                
        }
    }

    public int Count
    {
        get
        {
            return values_.Count;
        }
    }
}

 

در این کلاس فیلد _values ، Collection واقعی ما می باشد . متد GetIterator کلاس MyAggegate را به Constructor کلاس MyIterate پاس میدهد و یک شی از کلاس MyIterate بر می گرداند.

Property بعدی که ورودی آن ItemIndex می باشد باعث می شود که ما بتوانیم یک مقدار int را به صورت MyAggregate[int] به این Property پاس بدهیم.این Property مقدار ItemIndex را می گیرد.اگر مقداری در این Property ست شود ، این Property این مقدار را گرفته و به Collection ما یعنی Values اضافه می کند (Set) .اگر Get این Property فراخوانی شود یا چزی ازین Property بخواهد خوانده شود این Propety چک می کند که اگر مقدار ItemIndex از سایز Collection ما کوچک تر باشد مقداری را بر می گرداند که در ItemIndex  کالکشن موجود می باشد و اگر ItemIndex بزرگ تر از سایز Collection ما باشد مقدار خالی بر میگرداند.

آخرین Property هم Count می باشد که سایز فعلی Collection  ما را بر میگرداند.

کلاس بعدی که به سراغ پیاده سازی آن میرویم کلاس MyIterate می باشد.این کلاس اینترفیس IIterate را پیاده سازی می کند.

class MyIterator : IIterator
{
    IAggregate aggregate_ = null;
    int currentIndex_ = 0;

    public MyIterator(IAggregate aggregate)
    {
        aggregate_ = aggregate;
    }

    #region IIterator Members

    public string FirstItem
    {
        get
        {
            currentIndex_ = 0;
            return aggregate_[currentIndex_];
        }
    }

    public string NextItem
    {
        get
        {
            currentIndex_ += 1;

            if (IsDone == false)
            {
                return aggregate_[currentIndex_];
            }
            else
            {
                return string.Empty;
            }
        }
    }

    public string CurrentItem
    {
        get
        {
            return aggregate_[currentIndex_];
        }
    }

    public bool IsDone
    {
        get
        {
            if (currentIndex_ < aggregate_.Count)
            {
                return false;
            }
            return true;
        }
    }

    #endregion
}

 

این کلاس دو فیلد دارد.

۱-فیلدی از نوع کلاس Aggregate

۲-_currentIndex که وظیفه نگهداری Index فعلی را دارد.در Constructor این کلاس فیلد Aggregate مقدار دهی می شود.این کلاس دارای ۴ property  است که این Property ها همگی فقط چیزی را برمی گیردانند(فقط Get دارند و چیزی در آن ها توسط Client نمی تواند  Set نمی شود.

Property اول،FirstItem است .این Property با پاس دادن مقدار ۰ به کلاس Aggregate ، مقدار اولین خونه از Collection را به بر میگرداند.

Property بعدی ،یعنیNextItem با اضافه کردن یک واحد به cuurentIndex مقدار بعد از Index فعلی را به ما بر میگرداند.فقط در این Property اول مقدار IsDone که یک Propery دیگر از همین کلاس است چک می شود.وظیفه این  Property چک کردن این است که Index ما از سایز Collection فراتر نرود تا برنامه با خطا رو به رو نشود.Property آخر هم CurrentItem است که مقداری که در خانه CurrentIndex کالکشن ما می باشد را بر می گرداند.

حال به سادگی و با استفاده از کد زیر میتوانیم Collection را پیمایش کنیم بدون اینکه بخواهیم به طور مستقیم درگیر منطق پیمایش بشویم:

class Program
{
    static void Main(string[] args)
    {
        MyAggregate aggr = new MyAggregate();

        aggr[0] = "1";
        aggr[1] = "2";
        aggr[2] = "3";
        aggr[3] = "4";
        aggr[4] = "5";
        aggr[5] = "6";
        aggr[6] = "7";
        aggr[7] = "8";
        aggr[8] = "9";
        aggr[9] = "10";

        IIterator iter = aggr.GetIterator();

        for (string s = iter.FirstItem; iter.IsDone == false;  s = iter.NextItem )
        {
            Console.WriteLine(s);
        }
    }
}

 

در مطلب بعدی با هم Mediator را بررسی خواهیم کرد.موفق باشید.

منبع: http://www.codeproject.com/Articles/362986/Understanding-and-Implementing-the-Iterator-Patter