جلسه شماره 126رایگان

Builder Pattern in Java | الگوی بیلدر در جاوا

00:26:45

توضیحات جلسه

🎥 این ویدیو چهارمین قسمت از پلی‌لیست بررسی کتاب مرجع Effective Java است. 📚 در این جلسه، بررسی آیتم دوم از کتاب افکتیو جاوا را ادامه می‌دهیم و به یکی از پرکاربردترین الگوهای طراحی (Design Patterns) در توسعه نرم‌افزار یعنی Builder Pattern می‌پردازیم. در این ویدیو به طور کامل بررسی می‌کنیم که چرا استفاده از کانستراکتورهای طولانی (Telescoping Constructor) یا الگوی JavaBeans برای ساخت اشیاء پیچیده، مشکلاتی مانند ناخوانایی کد و عدم تغییرناپذیری (Immutability) ایجاد می‌کند. الگوی Builder راه‌حل استاندارد جاوا برای حل این مشکلات است که در این جلسه با مثال معروف Nutrition Facts آن را به صورت عملی پیاده‌سازی می‌کنیم. در این جلسه یاد می‌گیریم: ⚙️ مشکل ساخت اشیاء با پارامترهای زیاد و چرا الگوهای قدیمی ناکارآمد هستند 💡 ایده اصلی و فلسفه الگوی Builder در جاوا چیست 🧪 بررسی و پیاده‌سازی مثال کلاسیک Nutrition Facts از کتاب Effective Java ✅ مزایای استفاده از Builder برای خوانایی کد و مدیریت وضعیت شیء ⚠️ معایب و هزینه‌های اضافه کردن کد (Boilerplate) در این الگو 🧭 راهنمای عملی برای اینکه چه زمانی باید از Builder استفاده کنیم 🧠 در پایان نیز یک جمع‌بندی کامل از نکات مهم این مبحث خواهیم داشت اگر می‌خواهید کدهایی تمیز، ایمن و قابل نگهداری بنویسید، درک عمیق این الگو یکی از کلیدی‌ترین مهارت‌های شما به عنوان یک برنامه‌نویس جاوا خواهد بود. 📖 لینک دانلود کتاب: https://github.com/farzadafi/Teaching/blob/master/Book/EffectiveJava/2018-Effective%20Java.pdf 📌 یوتیوب: https://youtube.com/@farzadafi 📌 آپارات: https://aparat.com/farzadafi 📌 وب سایت: https://farzadafi.ir 📌 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi وب سایت: https://farzadafi.ir هر سوالی داشته باشید می‌توانید در گروه بپرسید تا خودم یا مربی‌هایی که در گروه حضور دارند کمکتان کنیم :) 🎯 بوت‌کمپ رایگان جاوا – آموزش کاملاً پروژه‌محور برای یادگیری عمیق جاوا و ورود به بازار کار.

جزوه و مستندات

مفاهیم کلیدی

  • Builder Pattern

الگوی طراحی سازنده‌ای که فرآیند ساخت شیء را گام‌به‌گام کرده و امکان ایجاد اشیاء تغییرناپذیر (immutable) را با پارامترهای اختیاری زیاد فراهم می‌کند. این الگو امنیت Telescoping Constructor را با خوانایی JavaBeans ترکیب می‌کند.

  • Telescoping Constructor Pattern

روشی سنتی که در آن چندین سازنده با تعداد پارامترهای افزایشی تعریف می‌شوند و هر سازنده، سازنده کامل‌تر را صدا می‌زند. این شیوه با افزایش پارامترها به شدت ناخوانا و غیرقابل توسعه می‌شود.

  • JavaBeans Pattern

رویکردی که در آن یک شیء با سازنده پیش‌فرض ساخته شده و سپس با متدهای setter مقداردهی می‌شود. این روش وضعیت ناسازگار موقت ایجاد کرده و امکان ساخت شیء تغییرناپذیر را از بین می‌برد.

  • Fluent API

روشی در طراحی متدها که در آن هر متد مرجع خود شیء (this) را بازمی‌گرداند تا بتوان فراخوانی متدها را به صورت زنجیره‌ای (method chaining) متصل کرد.

  • Invariant Check

بررسی صحت شروط منطقی حاکم بر مقادیر فیلدها که باید همواره برقرار باشند، به‌ویژه روابطی که صحت یک پارامتر را به مقدار پارامتر دیگر وابسته می‌کند.

  • Simulated Self-Type Idiom

راهکاری در جاوا برای شبیه‌سازی نوع بازگشتی شیء جاری در کلاس‌های والد، که با کمک یک پارامتر جنریک بازگشتی (recursive type parameter) و متد انتزاعی self پیاده‌سازی می‌شود تا زنجیره متدها در فرزندان نیازی به تبدیل نوع (cast) نداشته باشند.

  • Covariant Return Typing

قابلیتی در جاوا که به متد بازنویسی‌شده در زیرکلاس اجازه می‌دهد نوع بازگشتی تخصصی‌تری نسبت به متد کلاس والد برگرداند. این ویژگی باعث می‌شود متد build زیرکلاس مستقیماً نمونه همان کلاس را بازگرداند.

موارد مصاحبه ای

  • چرا با وجود سازنده‌ها و متدهای کارخانه‌ای استاتیک به الگوی Builder نیاز داریم؟

سازنده‌ها و static factory methods زمانی که تعداد پارامترهای اختیاری بالا می‌رود مقیاس‌پذیر نیستند و خوانایی کد در سمت کلاینت به شدت افت می‌کند.

  • تفاوت ایمنی Builder نسبت به الگوی JavaBeans چیست؟

در الگوی JavaBeans شیء در طول فراخوانی‌های متعدد متدهای setter در وضعیتی ناپایدار و ناسازگار (inconsistent state) قرار دارد و نمی‌توان آن را immutable کرد، اما در Builder شیء نهایی پس از اعتبارسنجی کامل و به صورت یکباره ساخته می‌شود.

  • اعتبارسنجی پارامترها در الگوی Builder در چه مراحلی انجام می‌شود؟

اعتبارسنجی مقادیر منفرد بلافاصله در متدهای setter بیلدر انجام می‌شود تا خطای اولیه سریع مشخص شود؛ اما اعتبارسنجی شروط ناوردا (invariants) که چند پارامتر را درگیر می‌کنند، درون متد build و قبل از ساخت نمونه نهایی بررسی می‌شود و در صورت نقض، استثنای IllegalArgumentException پرتاب می‌گردد.

  • مزیت Builder در برخورد با پارامترهای با طول متغیر (varargs) نسبت به سازنده‌ها چیست؟

سازنده‌ها تنها می‌توانند یک پارامتر varargs آن هم به عنوان آخرین پارامتر داشته باشند، اما در Builder می‌توان متدهای متعددی با قابلیت دریافت varargs تعریف کرد یا با چندین بار فراخوانی یک متد، داده‌ها را داخل یک فیلد یا مجموعه تجمیع نمود.

  • معایب استفاده از الگوی Builder چیست؟

هزینه جزئی ساخت شیء میانی بیلدر در حافظه (که در شرایط با کارایی بسیار بحرانی اهمیت می‌یابد) و افزایش حجم کدنویسی اولیه (verbosity)؛ به همین دلیل این الگو معمولاً برای کلاس‌هایی با ۴ پارامتر یا بیشتر توصیه می‌شود.

  • تکنیک Covariant Return Typing چه کمکی به بیلدرهای سلسله‌مراتبی می‌کند؟

این ویژگی باعث می‌شود که کلاینت بدون نیاز به تبدیل نوع دستی (type casting)، مستقیماً به متدها و نمونه‌های اختصاصی زیرکلاس دسترسی داشته باشد.

سناریو کاربردی

کلاس برچسب حقایق تغذیه‌ای (NutritionFacts) دارای دو پارامتر اجباری اندازه هر وعده و تعداد وعده در بسته است، اما بیش از ۲۰ پارامتر اختیاری مانند چربی کل، چربی اشباع، سدیم و کربوهیدرات دارد. اغلب مواد غذایی تنها برای چند مورد از این فیلدها مقدار دارند.

با استفاده از الگوی Builder، فیلدهای اجباری مستقیماً به سازنده بیلدر پاس داده می‌شوند و فیلدهای اختیاری از طریق متدهای زنجیره‌ای با مقادیر پیش‌فرض تنظیم می‌گردند:

ابتدا کلاینت شیء NutritionFacts.Builder را با مقادیر اجباری فراخوانی کرده، سپس متدهای زنجیره‌ای مانند calories(100) و sodium(35) را فراخوانی می‌کند و در نهایت با اجرای متد build، شیء نهایی و تغییرناپذیر تولید می‌شود. این شیوه رفتاری شبیه به پارامترهای نام‌دار در زبان‌هایی نظیر پایتون و اسکالا ایجاد می‌کند.

در سناریوی سلسله‌مراتب کلاس‌ها مانند انواع پیتزا (Pizza به عنوان کلاس پایه، و NyPizza و Calzone به عنوان زیرکلاس‌ها)، هر کلاس بیلدر موازی خود را دارد و پیاده‌سازی تکنیک self و covariant return typing اجازه می‌دهد ویژگی‌های اختصاصی هر پیتزا بدون شکستن زنجیره متدها ثبت شوند.

بیشتر بدانید

  • پیش‌بینی توسعه در آینده

اگر کلاسی در ابتدا پارامترهای کمی دارد اما احتمال اضافه شدن پارامترهای اختیاری در آینده وجود دارد، بهتر است از همان ابتدا با Builder طراحی شود؛ زیرا جایگزینی آن در آینده باعث باقی ماندن سازنده‌های منسوخ و ناهماهنگ در کدبیس می‌شود.

  • بازاستفاده از شیء بیلدر

یک شیء بیلدر می‌تواند منعطف باشد و چندین بار برای ساخت چندین شیء مورد استفاده قرار گیرد، یا در بین فراخوانی‌ها برخی فیلدهای آن بازتنظیم شوند.

  • تولید خودکار در IntelliJ

در محیط IntelliJ IDEA می‌توان با استفاده از قابلیت‌های تولید خودکار کد یا ابزارهایی نظیر کتابخانه Lombok و استفاده از انوتیشن @Builder، کدهای تکراری مربوط به الگوی بیلدر را بدون نیاز به پیاده‌سازی دستی ایجاد کرد.