الگوی طراحیِ Builder (جاوا و کاتلین)

بعضی وقتا شما نیاز داری مراحلِ ساخت یک object رو از هم جدا کنی ، مثلا وقتی که شئِ شما چندین اِلمان مختلف داره و خیلی جالب نیست یک constructor با 10 تا ورودی براش درست کنی ، همین طور وقتی که بعضی از اِلمان ها می‌تونن اختیاری باشن ، الگوی طراحی Builder در چنین شرایطی به ما کمک می‌کنه ، این الگو جزءِ طبقه Creational حساب میشه .ساخت یک شئ به صورت مرحله به مرحلهیک Builder از چند عضو تشکیل شده :Productکه میشه همون شئ که در انتها برای ما ساخته میشهBuilderیک Interface که تمامی توابع و step های مورد نظر رو درونش جا دادهConcrete Builderشامل پیاده سازی توابع تعریف شده در Builder هست که می‌تونیم چندین Concrete Builder داشته باشیمDirectorالگوریتمی که Product رو برای ما تولید می‎کنه رو کنترل می‌کنه ، در واقع این قسمت همون کاری رو می‎کنه که شما تو کد انجام می‎‌دید و چیز مجزایی نیست و اختیاری حساب میشه ، ما هم در مثالمون این قسمت رو چیز جدایی حساب نمی‌کنیمخب بهتره یه مثال ببینیم ، اول از همه بگم که تفاوتی در کاتلین و جاوا برای Builder وجود داره ، وقتی شما با جاوا بخواید Builder بنویسید باید هزار خط بنویسید :/ اما برای کاتلین به شدت کمتر میشه ، من در این مقاله برای هر دو این زبان ها مثال میارم و اول با جاوا شروع می‌کنم ، هدف اینه که یک شکل رو بسازیم ، این شکل این مولفه ها رو داره : 1.مساحت (اجباری) 2.محیط (اجباری) 3.رنگ (اختیاری) 4.اسم (اختیاری) برای این کار اول ShapeBuilderInterface رو ایجاد می‌کنیم : https://gist.github.com/sasssass/feb78fb0259c73559b47fa6b82d88f3b دقت کنید در کد بالا فقط رنگ و اسم رو آوردیم چون دو پارامتر اول اجباری بودن و اون رو در قسمت های دیگه اضافه می‌کنیم ، حالا نیازه کلاس Shape رو ایجاد کنیم و باقی کد ها باید در همین کلاس آورده بشن : https://gist.github.com/sasssass/301cdf48c285278a449ffac9d11ffce0 کلاسِ 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 نوشته شدند دسترسی داشته باشه و به عناصر دیگه دسترسی ندارهالگویِ طراحی Builder در Kotlinدر زبان کاتلین به خاطر ویژگی اسم گذاری پارامترها (یعنی اگه خواستید جا به جا عناصر رو بدید به صورت name = value توی constructor یا توابع یا ... مقداردهی می ‌کنید) و همین طوری وجود default value ها برای توابع و ... نیاز شدیدی به Builder احساس نمیشه و با خودِ کاتلین اونو انجام می‌دیم (در این مثال پارامتر ها رو به صورت جا به جا پاس میدم) : https://gist.github.com/sasssass/3fada76dfb35e48dcdbf36aac5aec0e7 https://gist.github.com/sasssass/fb3d4b7a37b5b02001f3823d72e6c19e نکته : دلیل خاصی نداشته که یکی از پارامتر ها رو به صورت apply گذاشتم ، فقط خواستم بدونید که این هم یکی دیگه از راه‌های مقداردهی در کاتلینه !ولی اگه حتما می‌خواید به صورت Builder باشه (قسمت ShapeBuilderInterface همون قبلی میشه و فرق خاصی نداره) : https://gist.github.com/sasssass/1cdf2813b8f29d048cb3f7f7a40c941e نکته : در کاتلین زمانی که فقط می‌خواید خروجی رو بدون انجام هیچ عملیات اضافه برگردونید مثل مثال بالا پروتوتایپ تابع رو برابر خروجی میذاریدو این هم از این ! در مقالات بعدی الگوهای طراحی بیشتری رو مورد بررسی قرار می‌دیم .باقی مقالات در مورد الگوی‌های طراحی رو در این مقاله بخونید .من رو در لینکدین و اینستاگرام دنبال کنید ???اگه دوست داشتید می‌تونید به صفحه Spotify بنده هم برید و موسیقی های منو گوش بدید ???