بعضی ار مردم نمی توانند زندگی را بدون قهوه تصور کنند و بعضی دیگر زندگی را بدون چای نمی توانند تصور کنند. ولی جزء تشکیل دهنده اصلی هر دو کافئین است. شباهت های دیگر نیز بین این دو مورد وجود دارد. روش ساخت هر دوی آنها تقریبا مشابه است. شما اغلب موارد به ترتیب زیر عمل می کنید.
دستوالعمل ساخت قهوه:
1. مقداری آب را می جوشانید.
2. مقدار قهوه در آب جوشانده شده می ریزد تا دم بکشد.
3. فهوه را در فنجان می ریزد.
4. مقداری شکر و یا شیر به آن اضافه می کنید.
دستورالعمل ساخت چای:
1. مقداری آب را می جوشانید.
2. مقدار چای خشک در آب جوشانده شده می ریزد تا دم بکشد.
3. چای را در فنجان می ریزد.
4. مقداری شکر به آن اضافه می کنید.
اگر بخواهیم برنامه ای برای تهیه چای و قهوه بنویسیم کلاس های را به صورت زیر خواهیم داشت.
کلاس قهوه |
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 در هر کلاس به صورت نتفاوت عمل می کند. این متد در زیر کلاس های مربوطه پیاده سازی می شود.
طراحی بالا یک طراحی خوب است اما نمی شود طراحی را بهتر از این کرد؟ اگر توجه کنیم متوجه می شویم که برای تهیه هر دو مورد الگوریتم یکسانی را به کار می بریم:
1. جوشاندن آبی
2. اضافه کردن چای یا قهوه به آب جوشیده شده
3. ریختن نوشیدنی به دست امده در فنجان
4. اضافه کردن چاشنی مورد نظر به نوشیدنی
پس ما می توانیم با کمی تغییرات متد 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 وجود داشته باشد. این حالت زمانی رخ می دهد که بعضی از مراحل الگوریتم بتواند در روش های مختلف پیاده سازی شود.