حوزه: Class
هدف: Behavioral
نقش الگو
بعضی از مردم نمیتوانند زندگی را بدون قهوه تصور کنند و بعضی دیگر زندگی را بدون چای نمیتوانند تصور کنند. ولی جزء تشکیل دهنده اصلی هر دو کافئین است. شباهتهای دیگر نیز بین این دو مورد وجود دارد. روش ساخت هر دوی آنها تقریبا مشابه است. شما اغلب موارد به ترتیب زیر عمل میکنید.
دستوالعمل ساخت قهوه:
- مقداری آب را میجوشانید.
- مقدار قهوه در آب جوشانده شده میریزد تا دم بکشد.
- قهوه را در فنجان میریزد.
- مقداری شکر و یا شیر به آن اضافه میکنید.
دستورالعمل ساخت چای:
- مقداری آب را میجوشانید.
- مقدار چای خشک در آب جوشانده شده میریزد تا دم بکشد.
- چای را در فنجان میریزد.
- مقداری شکر به آن اضافه میکنید.
اگر بخواهیم برنامهای برای تهیه چای و قهوه بنویسیم کلاسهایی به صورت زیر خواهیم داشت.
public class Coffee {
public void prepareRecipe() {
boilWater();
brewCoffeeGrinds();
pourInCup();
addSugereAndMilk();
}
public void boilWater() {
System.out.println("جوشاندن آب");
}
public void brewCoffeeGrinds() {
System.out.println("ریختن پودر قهوه به داخل آب جوشانده شده");
}
public void pourInCup() {
System.out.println("ریختن قهوه به فنجان");
}
public void addSugereAndMilk() {
System.out.println("اضافه کردن شیر و شکر");
}
}
public class Tea {با مشاهده دو کلاس بالا مشاهده میشود که دو متد boilWater و pourInCup دقیقا مشابه یکدیگر هستند. پس طراحی ما دارای اشتباه هست چون بعضی از کدها تکرار شدهاند. پس ما باید طراحی خود را تغییر دهیم. ما میتوانیم طراحی خود را به صورت زیر تغییر دهیم. دو متد کاملا مشابه در کلاس پایه پیاده سازی می شود. اما چون متد prepareRecipe در هر کلاس به صورت متفاوت عمل میکند. این متد در زیر کلاسهای مربوطه پیاده سازی میشود.
public void prepareRecipe() {
boilWater();
brewTea();
pourInCup();
addSugere();
}
public void boilWater() {
System.out.println("جوشاندن آب");
}
public void brewTea() {
System.out.println("ریختن چای به داخل آب جوشانده شده");
}
public void pourInCup() {
System.out.println("ریختن چای به فنجان");
}
public void addSugere() {
System.out.println("اضافه کردن شکر");
}
}
طراحی بالا یک طراحی خوب است اما نمیشود طراحی را بهتر از این کرد؟ اگر توجه کنیم متوجه میشویم که برای تهیه هر دو مورد الگوریتم یکسانی را به کار میبریم:
- جوشاندن آبی
- اضافه کردن چای یا قهوه به آب جوشیده شده
- ریختن نوشیدنی به دست امده در فنجان
- اضافه کردن چاشنی مورد نظر به نوشیدنی
public void prepareRecipe() {
boilWater();
brewCoffeeGrinds();
pourInCup();
addSugereAndMilk();
}
public void prepareRecipe() {
boilWater();
brewTea();
pourInCup();
addSugere();
}
همانطوریکه میتوانید مشاهده کنید کلاس مر بوط به قهوه متدهای به نام brewCoffeeGrinds و addSugereAndMilk را استفاده میکند در حالیکه کلاس مربوط به چای از متدهای به نام brewTea و addSugere استفاده میکند. یک راه حل این است که برای هر مرحله غیر مشابه یک نام مشترک در نظر بگیریم. نام متدهای brewTea و brewCoffeeGrinds را به brew تغییر دهیم و نام متدهای addSugereAndMilk و addSugere را به addCondiments تغییر میدهیم. پس متد prepareRecipe برای هر دو کلاس به صورت زیر تغییر میکند.
public void prepareRecipe() {پس حالا میتوانیم این متد را بطور کامل به کلاس پایه منتقل کنیم و طراحی را به صورت زیر تغییر دهیم.
boilWater();
brew();
pourInCup();
addCondiments();
}
حالا ما برای این مسله به یک طراحی ائده ال دست یافتیم. کاری که ما برای حل این مسله انجام دادیم به نام الگوی Template method شناخته میشود. دلیل نامگذاری این الگو را میتوانیم با مشاهده متد prepareRecipe از کلاس پایه درک کنیم. اولین اینکه prepareRecipe یک متد است و دوما به عنوان یک قالب برای الگوریتم به کار میرود. برای نمونه در این مثال شامل الگوریتم تهیه یک نوشیدنی میباشد.
الگوی Template method، مراحل انجام یک الگوریتم را در یک متد در کلاس پایه تعریف میکند و اجازه میدهد زیر کلاسها یک یا چند مرحله از الگوریتم را پیاده سازی کنند. در واقع اسکلت یک الگوریتم در یک متد تعریف میشود.
هدف ما در این الگو، ایجاد یک قالب برای یک الگوریتم است. یک قالب یک الگوریتم را به صورت مجموعهای از مراحل تعریف میکند. هر کدام از این مراحل به عنوان یک متد در نظر گرفته میشود. که بعضی از متدها در همان کلاس پایه پیاده سازی میشود و بعضی از متدها به صورت abstract در کلاس پایه در نظر گرفته میشود و در زیر کلاس ها پیاده سازی میشود.
الگوی Template method، مراحل انجام یک الگوریتم را در یک متد در کلاس پایه تعریف میکند و اجازه میدهد زیر کلاسها یک یا چند مرحله از الگوریتم را پیاده سازی کنند. در واقع اسکلت یک الگوریتم در یک متد تعریف میشود.
هدف ما در این الگو، ایجاد یک قالب برای یک الگوریتم است. یک قالب یک الگوریتم را به صورت مجموعهای از مراحل تعریف میکند. هر کدام از این مراحل به عنوان یک متد در نظر گرفته میشود. که بعضی از متدها در همان کلاس پایه پیاده سازی میشود و بعضی از متدها به صورت abstract در کلاس پایه در نظر گرفته میشود و در زیر کلاس ها پیاده سازی میشود.
نمودار UML :
نمودار UML این الگو به صورت بالا است. که در آن کلاس AbstractClass یک کلاس Abstract است که الگوی قالب در آن تعریف میشود و متد primitiveOperation یک متد Abstract است (یک مرحله از الگوریتم) که در زیر کلاس پیاده سازی خواهد شد. همانطوریکه در مثال بالا مشاهده کردیم میتواند بیش از یک کلاس ConcerteClass وجود داشته باشد. این حالت زمانی رخ میدهد که بعضی از مراحل الگوریتم بتواند در روشهای مختلف پیاده سازی شود.
مثال پیاده سازی شده با زبان جاوا را میتوانید از github من دانلود کنید.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.