بعضی وقتا شما نیاز داری مراحلِ ساخت یک object رو از هم جدا کنی ، مثلا وقتی که شئِ شما چندین اِلمان مختلف داره و خیلی جالب نیست یک constructor با 10 تا ورودی براش درست کنی ، همین طور وقتی که بعضی از اِلمان ها میتونن اختیاری باشن ، الگوی طراحی Builder در چنین شرایطی به ما کمک میکنه ، این الگو جزءِ طبقه Creational حساب میشه .
یک Builder از چند عضو تشکیل شده :
که میشه همون شئ که در انتها برای ما ساخته میشه
یک Interface که تمامی توابع و step های مورد نظر رو درونش جا داده
شامل پیاده سازی توابع تعریف شده در Builder هست که میتونیم چندین Concrete Builder داشته باشیم
الگوریتمی که Product رو برای ما تولید میکنه رو کنترل میکنه ، در واقع این قسمت همون کاری رو میکنه که شما تو کد انجام میدید و چیز مجزایی نیست و اختیاری حساب میشه ، ما هم در مثالمون این قسمت رو چیز جدایی حساب نمیکنیم
خب بهتره یه مثال ببینیم ، اول از همه بگم که تفاوتی در کاتلین و جاوا برای Builder وجود داره ، وقتی شما با جاوا بخواید Builder بنویسید باید هزار خط بنویسید :/ اما برای کاتلین به شدت کمتر میشه ، من در این مقاله برای هر دو این زبان ها مثال میارم و اول با جاوا شروع میکنم ، هدف اینه که یک شکل رو بسازیم ، این شکل این مولفه ها رو داره : 1.مساحت (اجباری) 2.محیط (اجباری) 3.رنگ (اختیاری) 4.اسم (اختیاری)
برای این کار اول ShapeBuilderInterface رو ایجاد میکنیم :
دقت کنید در کد بالا فقط رنگ و اسم رو آوردیم چون دو پارامتر اول اجباری بودن و اون رو در قسمت های دیگه اضافه میکنیم ، حالا نیازه کلاس Shape رو ایجاد کنیم و باقی کد ها باید در همین کلاس آورده بشن :
کلاسِ Shape خودش چهار پارامتر رو داره و constructor اون به صورت private آورده شده که ما حتما مجبور به استفاده از Builder بشیم و نتونیم حالت عادی ازش شئ بگیریم ، کلاس ShapeBuilder که implement شده از ShapeBuilderInterface هست دو پارامتر رو به صورت اجباری در constructor داره و باقی به صورت توابع override شده هستن ، به صورت دیفالت هم رنگ 0 و اسم undefined گذاشته شده ، دو پارامتر محیط و مساحت به دلیل اینکه قرار نیست در این قسمت اضافه بشن (به صورت step by step) پس تغییری ندارن و final میشن ، در نهایت ما با تابع build یک خروجی از جنس مورد نظرمون داریم :
Shape shape = new Shape.ShapeBuilder(10, 10).addColor(Color.BLACK).addName("").build();
نکته : چرا ما کلاس ShapeBuilder رو به صورت static در آوردیم ؟ اگر کلاسی رو داخل کلاس دیگه تعریف کنید و بخواید ازش شئ بگیرید نیاز دارید که قبلش یه شئ از کلاس قبلی داشته باشید ، اما اگه به صورت static تعریف بشه مثل دو کلاس جدا از هم باهاشون برخورد میشه ، یک تفاوت دیگه در کلاسی که به صورت static نوشته شده اینه که فقط میتونه به عناصری که در کلاس بیرونی به صورت static نوشته شدند دسترسی داشته باشه و به عناصر دیگه دسترسی نداره
در زبان کاتلین به خاطر ویژگی اسم گذاری پارامترها (یعنی اگه خواستید جا به جا عناصر رو بدید به صورت name = value توی constructor یا توابع یا ... مقداردهی می کنید) و همین طوری وجود default value ها برای توابع و ... نیاز شدیدی به Builder احساس نمیشه و با خودِ کاتلین اونو انجام میدیم (در این مثال پارامتر ها رو به صورت جا به جا پاس میدم) :
نکته : دلیل خاصی نداشته که یکی از پارامتر ها رو به صورت apply گذاشتم ، فقط خواستم بدونید که این هم یکی دیگه از راههای مقداردهی در کاتلینه !
ولی اگه حتما میخواید به صورت Builder باشه (قسمت ShapeBuilderInterface همون قبلی میشه و فرق خاصی نداره) :
نکته : در کاتلین زمانی که فقط میخواید خروجی رو بدون انجام هیچ عملیات اضافه برگردونید مثل مثال بالا پروتوتایپ تابع رو برابر خروجی میذارید
و این هم از این ! در مقالات بعدی الگوهای طراحی بیشتری رو مورد بررسی قرار میدیم .
باقی مقالات در مورد الگویهای طراحی رو در این مقاله بخونید .
من رو در لینکدین و اینستاگرام دنبال کنید ???
اگه دوست داشتید میتونید به صفحه Spotify بنده هم برید و موسیقی های منو گوش بدید ???