بایگانی

بایگانی فروردین

الگوی استراتژی (Strategy Pattern)

۳۱ فروردین ۱۳۸۶ ۴ دیدگاه

در زندگی روزمره خود به مسائلی برخورد می کنیم و برای غلبه بر این مسائل ممکن است چندین راه حل پیش رو داشته باشیم. ما با توجه به شرایط خود یا به اجبار یکی از این راه حل ها را انتخاب می کنیم. در طراحی و پیاده سازی یک نرم افزار نیز این شرایط وجود دارد یعنی جهت انجام یک عمل خاص می توانیم از چندین الگوریتم خاص استفاده کنیم در این حالت می توانیم برنامه را طوری طراحی کنیم که خود برنامه به صورت پویا الگوریتم با بازدهی بالاتر را اتنخاب کند یا این امکان را به برنامه کلاینت یا  کاربر بدهیم تا یکی از الگوریتم ها را جهت انجام آن عمل انتخاب کند.

برای مثال فرض کنید که ما در حال طراحی یک برنامه مسیریابی برای یک شبکه هستیم. همانطوریکه می دانیم برای مسیر یابی الگوریتم های مختلفی وجود دارد که هر کدام دارای مزایا و معایبی هستند. و با توجه به وضعیت موجود شبکه یا عملی که قرار است انجام پذیرد باید الگوریتمی را که دارای بالاترین کارائی است انتخاب کنیم. همچنین این برنامه باید امکانی را به کاربر بدهد که کارائی الگوریتم های مختلف را در یک شبکه فرضی بررسی کنید. حالا طراحی پیشنهادی شما برای این مسله چست؟

دوباره فرض کنید که در مثال بالا در بعضی از الگوریتم ها نیاز داریم که گره های شبکه را بر اساس فاصله ی آنها از گره مبداء مرتب کنیم. دوباره برای مرتب سازی الگوریتم های مختلف وجود دارد و هر کدام در شرایط خاص، کارائی بهتری نسبت به الگوریتم های دیگر دارد. مسئله دقیقا شبیه مسئله بالا است و این مسله می توانند دارای طراحی شبیه مسله بالا باشد. پس اگر ما بتوانیم یک طراحی خوب برای این مسئله ارائه دهیم می توانیم این طراحی را برای مسائل مشابه به کار ببریم.

هر کدام از ما می توانیم نسبت به درک خود از مسئله و سلیقه کاری، طراح های مختلفی برای این مسئله ارائه دهیم. اما یک طراحی که می تواند یک جواب خوب و عالی باشد، الگوی استراتژی است که توانسته است بارها و بارها به این مسئله پاسخ بدهد.

الگوی استراتژی گزینه مناسبی برای مسائلی است که می توانند از چندین الگوریتم مختلف به مقصود خود برسند.

نمودار UML این الگو بصورت زیر است:

 

اجازه بدهید، شیوه کار این الگو را با مثال مربوط به مرتب سازی بررسی کنیم. فرض کنید که ما تصمیم گرفتیم که از سه الگویتم زیر برای مرتب سازی استفاده کنیم.

۱

Shell Sort

۲

Quick Sort

۳

Merge Sort

ما برای مرتب سازی در این برنامه دارای سه استراتژی هستیم. که هر کدام را به عنوان یک کلاس جداگانه در نظر می گیریم (همان کلاس های ConcreteStrategy). برای اینکه کلاس Client  بتواند به سادگی یک از استراتژی ها را انتخاب کنید بهتر است که تمام کلاس های استراتزی دارای اینترفیس مشترک باشند. برای این کار می توانیم یک کلاس abstract تعریف کنیم و ویژگیهای مشترک کلاس های استراتژی را در آن قرار دهیم و کلاس های استراتژی آنها را به ارث ببرند(همان کلاس Strategy) و پیاده سازی کنند.

کلاس abstract که کلاس های استراتژی آنرا به ارث می برند.

abstract class SortStrategy

    {

        public abstract void Sort(ArrayList list);

    }

 

کلاس مربوط به QuickSort

class QuickSort : SortStrategy

    {

        public override void Sort(ArrayList list)

        {

          // الگوریتم مربوطه   

        }

    }

 

کلاس مربوط به ShellSort

    class ShellSort : SortStrategy

    {

        public override void Sort(ArrayList list)

        {

          // الگوریتم مربوطه

        }

    }

 

کلاس مربوط به MergeSort

    class MergeSort : SortStrategy

    {

        public override void Sort(ArrayList list)

        {

          // الگوریتم مربوطه

        }

    }

 

کلاس Context که یکی از استراتزیها را برای مرتب کردن لیست به کار می برد.

    class SortedList

    {

        private ArrayList list = new ArrayList();

        private SortStrategy sortstrategy;

 

        public void SetSortStrategy(SortStrategy sortstrategy)

        {

            this.sortstrategy = sortstrategy;

        }

 

        public void Add(string name)

        {

            list.Add(name);

        }

 

        public void Sort()

        {

            sortstrategy.Sort(list);

        }

    }

 

  

الگو

۳۱ فروردین ۱۳۸۶ بدون دیدگاه

از شخص پرسیدند:

بهترین الگو برای پیروی چیست؟ افراد پرهیزگاری که زندگی شان را وقف خدا می کنند و نمی پرسند چرا؟ یا افراد با فرهنگی که می کوشند باری تعالی را بفهمند.

او گفت : بهتر از همه، الگوی کودکان است.

گفتند: کودک هیچ نمی داند. هنوز نمی داند واقعیت چیست؟

او جواب داد: سخت در اشتباهید. کودک چهار خاصیت دارد که هرگز نباید فراموش کنیم. همیشه بی دلیل شاد است. همیشه سرش به کاری مشغول است. وقتی چیزی را می خواهد، تا آن را نگیرد، از عزم و اصرارش کم نمی شود. سر انجام ، می تواند خیلی راحت گریه کند.

 

Categories: غیرفنی Tags:

الگوی Template method

۱۴ فروردین ۱۳۸۶ ۳ دیدگاه

 

بعضی ار مردم نمی توانند زندگی را بدون قهوه تصور کنند و بعضی دیگر زندگی را بدون چای نمی توانند تصور کنند. ولی جزء تشکیل دهنده اصلی هر دو کافئین است. شباهت های دیگر نیز بین این دو مورد وجود دارد. روش ساخت هر دوی آنها تقریبا مشابه است. شما اغلب موارد به ترتیب زیر عمل می کنید.

دستوالعمل ساخت قهوه:

۱٫       مقداری آب را می جوشانید.

۲٫       مقدار قهوه در آب جوشانده شده می ریزد تا دم بکشد.

۳٫       فهوه را در فنجان می ریزد.

۴٫       مقداری شکر و یا شیر به آن اضافه می کنید.

دستورالعمل ساخت چای:

۱٫       مقداری آب را می جوشانید.

۲٫       مقدار چای خشک در آب جوشانده شده می ریزد تا دم بکشد.

۳٫       چای را در فنجان می ریزد.

 

۴٫       مقداری شکر به آن اضافه می کنید.

 

 

اگر بخواهیم برنامه ای برای تهیه چای و قهوه بنویسیم کلاس های را به صورت زیر خواهیم داشت.

 

کلاس قهوه

Public Class Coffee

    هر مرحله از دستورالعمل ساخت قهوه به عنوان یک متد در نظر گرفته شده است.

    Public Sub prepareRecipe()

        مراحل تهیه قهوه

        boilWater()

        brewCoffeeGrinds()

        pourInCup()

        addSugereAndMilk()

    End Sub

    Public Sub boilWater()

        Console.WriteLine(جوشاندن آب)

    End Sub

    Public Sub brewCoffeeGrinds()

        Console.WriteLine(ریختن پودر قهوه به داخل آب جوشانده شده)

    End Sub

    Public Sub pourInCup()

        Console.WriteLine(ریختن قهوه به فنجان)

    End Sub

    Public Sub addSugereAndMilk()

        Console.WriteLine(اضافه کردن شیر و شکر)

    End Sub

End Class

 

 

کلاس چای

Public Class Tea

    Public Sub prepareRecipe()

        boilWater()

        brewTea()

        pourInCup()

        addSugere()

    End Sub

    Public Sub boilWater()

        Console.WriteLine(جوشاندن آب)

    End Sub

    Public Sub brewTea()

        Console.WriteLine(ریختن چای به داخل آب جوشانده شده)

    End Sub

    Public Sub pourInCup()

        Console.WriteLine(ریختن چای به فنجان)

    End Sub

    Public Sub addSugere()

        Console.WriteLine(اضافه کردن شکر)

    End Sub

End Class

 

 با مشاهده دو کلاس بالا مشاهده می شود که دو متد boilWater و pourInCup دقیقا مشابه یکدیگر هستند. پس طراحی ما دارای اشتباه هست چون بعضی از کدها تکرار شده اند. پس ما باید طراحی خود را تغییر دهیم. ما می توانیم طراحی خود را به صورت زیر تغییر دهیم. دو متد کاملا مشابه در کلاس پایه پیاده سازی می شود. اما چون متد prepareRecipe در هر کلاس به صورت نتفاوت عمل می کند. این متد در زیر کلاس های مربوطه پیاده سازی می شود.

طراحی بالا یک طراحی خوب است اما نمی شود طراحی را بهتر از این کرد؟   اگر توجه کنیم متوجه می شویم که برای تهیه هر دو مورد الگوریتم یکسانی را به کار می بریم:

۱٫       جوشاندن آبی

۲٫       اضافه کردن چای یا قهوه به آب جوشیده شده

۳٫       ریختن نوشیدنی به دست امده در فنجان

۴٫       اضافه کردن چاشنی مورد نظر به نوشیدنی

پس ما می توانیم با کمی تغییرات متد prepareRecipe را در کلاس پایه پیاده سازی کنیم.

 Public Sub prepareRecipe()

        boilWater()

        brewTea()

        pourInCup()

        addSugere()

 End Sub

 

Public Sub prepareRecipe()

        boilWater()

        brewCoffeeGrinds()

        pourInCup()

        addSugereAndMilk()

End Sub

 

 همانطوریکه می توانید مشاهده کنید کلاس مر بوط به قهوه متدهای به نام brewCoffeeGrinds و addSugereAndMilk را استفاده می کند در حالیکه کلاس مربوط به چای از متد های به نام brewTea و addSugere استفاده می کند. یک راه حل این است که برای هر مرحله غیر مشابه یک نام مشترک در نظر بگیریم. نام متدهای brewTea و brewCoffeeGrinds را به brew تغییر دهیم. و نام متدهای addSugereAndMilk و addSugere را به addCondiments  تغییر می دهیم. پس متد prepareRecipe برای هر دو کلاس به صورت زیر تغییر می کند.

Public Sub prepareRecipe()

        boilWater()

        brew ()

        pourInCup()

        addCondiments()

End Sub

 

 پس حالا می توانیم این متد را بطور کامل به کلاس پایه منتقل کنیم و طراحی را به صورت زیر تغییر دهیم.

حالا ما برای این مسله به یک طراحی ائده ال دست یافتیم. کاری که ما برای حل این مسله انجام دادیم به نام الگوی Template method  شناخته می شود. دلیل نامگذاری این الگو را می توانیم با مشاهده متد prepareRecipe از کلاس پایه درک کنیم. اولین اینکه prepareRecipe یک متد است و دوما به عنوان یک قالب برای الگوریتم به کار می رود. برای نمونه در این مثال شامل الگوریتم تهیه یک نوشیدنی می باشد.

الگوی Template method، مراحل انجام یک الگوریتم را در یک متد در کلاس پایه تعریف می کند و اجازه می دهد زیر کلاس ها یک یا چند مرحله از الگوریتم را پیاده سازی کنند. در واقع اسکلت یک الگوریتم در یک متد تعریف می شود.

هدف ما در این الگو، ایجاد یک قالب برای یک الگوریتم است. یک قالب یک الگوریتم را به صورت مجموعه ای از مراحل تعریف می کند. هر کدام از این مراحل به عنوان یک متد در نظر گرفته می شود. که بعضی از متدها در همان کلاس پایه پیاده سازی می شود و بعضی از متدها به صورت abstract در کلاس پایه در نظر گرفته می شود و در زیر کلاس ها پیاده سازی می شود.

نمودار UML :

نمودار UML این الگو به صورت بالا است. که در آن کلاس AbstractClass یک کلاس Abstract  است. که الگوی قالب در آن تعریف می شود. و متد primitiveOperation یک متد Abstract  است (یک مرحله از الگوریتم) که در زیر کلاس پیاده سازی خواهد شد. همانطوریکه در مثال بالا مشاهده کردیم می تواند بیش از یک کلاس ConcerteClass وجود داشته باشد. این حالت زمانی رخ می دهد که بعضی از مراحل الگوریتم بتواند در روش های مختلف پیاده سازی شود.

 

سال نو

۱۴ فروردین ۱۳۸۶ بدون دیدگاه

با تاخیر چند روزه، سال نو را به همه دوستان تبریگ گفته و آروزی سالی سر شار از موفقیت را برای آنها دارم.

دوست دارم سال نو، سالی نو برای همه باشد و بتوانیم در این سال نو بودن و تازگی را تجربه کنیم.

Categories: غیرفنی Tags: