در زندگی روزمره خود به مسائلی برخورد می کنیم و برای غلبه بر این مسائل ممکن است چندین راه حل پیش رو داشته باشیم. ما با توجه به شرایط خود یا به اجبار یکی از این راه حل ها را انتخاب می کنیم. در طراحی و پیاده سازی یک نرم افزار نیز این شرایط وجود دارد یعنی جهت انجام یک عمل خاص می توانیم از چندین الگوریتم خاص استفاده کنیم در این حالت می توانیم برنامه را طوری طراحی کنیم که خود برنامه به صورت پویا الگوریتم با بازدهی بالاتر را اتنخاب کند یا این امکان را به برنامه کلاینت یا کاربر بدهیم تا یکی از الگوریتم ها را جهت انجام آن عمل انتخاب کند.
برای مثال فرض کنید که ما در حال طراحی یک برنامه مسیریابی برای یک شبکه هستیم. همانطوریکه می دانیم برای مسیر یابی الگوریتم های مختلفی وجود دارد که هر کدام دارای مزایا و معایبی هستند. و با توجه به وضعیت موجود شبکه یا عملی که قرار است انجام پذیرد باید الگوریتمی را که دارای بالاترین کارائی است انتخاب کنیم. همچنین این برنامه باید امکانی را به کاربر بدهد که کارائی الگوریتم های مختلف را در یک شبکه فرضی بررسی کنید. حالا طراحی پیشنهادی شما برای این مسله چست؟
دوباره فرض کنید که در مثال بالا در بعضی از الگوریتم ها نیاز داریم که گره های شبکه را بر اساس فاصله ی آنها از گره مبداء مرتب کنیم. دوباره برای مرتب سازی الگوریتم های مختلف وجود دارد و هر کدام در شرایط خاص، کارائی بهتری نسبت به الگوریتم های دیگر دارد. مسئله دقیقا شبیه مسئله بالا است و این مسله می توانند دارای طراحی شبیه مسله بالا باشد. پس اگر ما بتوانیم یک طراحی خوب برای این مسئله ارائه دهیم می توانیم این طراحی را برای مسائل مشابه به کار ببریم.
هر کدام از ما می توانیم نسبت به درک خود از مسئله و سلیقه کاری، طراح های مختلفی برای این مسئله ارائه دهیم. اما یک طراحی که می تواند یک جواب خوب و عالی باشد، الگوی استراتژی است که توانسته است بارها و بارها به این مسئله پاسخ بدهد.
الگوی استراتژی گزینه مناسبی برای مسائلی است که می توانند از چندین الگوریتم مختلف به مقصود خود برسند.
نمودار UML این الگو بصورت زیر است:
اجازه بدهید، شیوه کار این الگو را با مثال مربوط به مرتب سازی بررسی کنیم. فرض کنید که ما تصمیم گرفتیم که از سه الگویتم زیر برای مرتب سازی استفاده کنیم.
1 |
Shell Sort |
2 |
Quick Sort |
3 |
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); } }
|