الگوی طراحی سازنده – انجمن DEV

Summarize this content to 400 words in Persian Lang
Builder Pattern یک الگوی طراحی خلاقانه است که راهی برای ساختن اشیاء پیچیده گام به گام ارائه می دهد. ساخت یک شی را از نمایش آن جدا می کند و به همان فرآیند ساخت اجازه می دهد تا انواع و نمایش های مختلفی از اشیاء را ایجاد کند.
حال این سوال پیش می آید که چرا به الگوی طراحی سازنده نیاز داریم، با چه مشکلی مواجه هستیم؟
در هنگام ایجاد شیء زمانی که شیء حاوی ویژگی های زیادی باشد، مشکلات زیادی وجود دارد:
برای ایجاد شی باید آرگومان های زیادی را پاس کنیم
برخی از پارامترها ممکن است اختیاری باشند
کلاس کارخانه تمام مسئولیت ایجاد شی را بر عهده می گیرد. اگر جسم سنگین باشد، تمام پیچیدگی ها بخشی از کلاس کارخانه است
بنابراین در بیلدر پترن مزایای متعددی را به خصوص در هنگام ساخت اشیاء پیچیده ارائه می دهد و برای ایجاد گام به گام شیء و در نهایت برگرداندن شی با مقادیر مشخصه دلخواه استفاده می شود.
الگوی سازنده را می توان با یک تشبیه ساده توضیح داد: سفارش یک پیتزا سفارشی.
سناریوی بدون الگوی سازنده:
تصور کنید به یک پیتزا فروشی می روید و فقط یک گزینه برای سفارش پیتزا به شما داده می شود: باید همه چیز را یکجا مشخص کنید – نوع پوسته، اندازه، سس، رویه ها و مواد اضافی. اگر چیزی را نادیده گرفتید یا به اشتباه مشخص کردید، پیتزا 🍕 ممکن است آنطور که می خواهید پیش نیاید و باید کل فرآیند را از ابتدا دوباره انجام دهید. این مانند استفاده از سازنده ای با پارامترهای زیاد است – مستعد خطا و مدیریت آن دشوار است، به خصوص زمانی که گزینه ها یا موارد اختیاری زیادی وجود دارد.
مثال بدون سازنده:
“من یک پیتزا 🍕 با پوسته نازک، اندازه متوسط، سس گوجه فرنگی، قارچ، پنیر🧀، بدون زیتون🍅، و ریحان اضافه می خواهم.” اگر چیزی را از دست دادید، باید از نو شروع کنید!سناریوی با الگوی سازنده:اکنون، به یک رویکرد انعطافپذیرتر فکر کنید که در آن پیتزاساز گام به گام تنظیمات خود را از شما میخواهد:
ابتدا می پرسند چه سایزی می خواهید.سپس در مورد نوع پوسته می پرسند.در مرحله بعد، آنها در مورد تاپینگ ها می پرسند.در نهایت، آنها از شما می پرسند که آیا چیزهای اضافی مانند پنیر اضافی یا سس خاصی می خواهید.در هر مرحله بر اساس آنچه می خواهید تصمیم می گیرید و در انتها پیتزای کاملا متناسب با سلیقه خود دریافت می کنید. لازم نیست نگران به خاطر سپردن یا مشخص کردن همه چیز به یکباره باشید. هر انتخاب بر اساس انتخاب قبلی است.
مثال با بیلدر:
“من یک پیتزا متوسط می خواهم.””من پوسته نازک می خواهم.””قارچ و پنیر را اضافه کنید.””زیتون نه، لطفا.””ریحان اضافی اضافه کنید.”Builder Pattern اجازه می دهد تا یک فرآیند گام به گام و ساختار یافته را انجام دهید، جایی که شما شی (یا پیتزا!) خود را به صورت تدریجی می سازید، که منجر به انعطاف پذیری بیشتر و اشتباهات کمتر می شود.
در اینجا چند نکته وجود دارد که مشاهده کردهام چگونه الگوی سازنده به شما برتری نسبت به سایر رویکردها مانند سازندههای تلسکوپ یا تنظیمکنندهها میدهد:
1). ساخت شی را با پارامترهای زیاد ساده می کند
هنگامی که یک شی دارای پارامترهای اختیاری یا اجباری زیادی است، استفاده از یک سازنده استاندارد می تواند گیج کننده و مستعد خطا باشد.
Builder Pattern یک رویکرد واضح و گام به گام برای ایجاد شی ارائه میدهد و تنظیم تنها ویژگیهای لازم را بدون نگرانی در مورد ترتیب پارامترها آسانتر میکند.
مثال: به جای این سازنده گیج کننده:
const car = new Car(‘Tesla’, ‘Model S’, 2024, ‘Red’, true, false);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
شما این کد قابل خواندن را دریافت می کنید:
const car = new CarBuilder(‘Tesla’, ‘Model S’)
.setYear(2024)
.setColor(‘Red’)
.addGPS()
.build();
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
2). پشتیبانی از رابط فلوئنت (زنجیره کردن روش)
رابط روان به روشها اجازه میدهد تا خود شی سازنده را برگردانند و زنجیرهبندی متد را ممکن میسازد. این باعث میشود کد بصریتر و خواناتر باشد، زیرا یک فرآیند منطقی و گام به گام برای تنظیم ویژگیها ارائه میکند.
مزیت: هر فراخوانی متد مانند دنباله ای از دستورالعمل ها برای ساخت شی خوانده می شود و خوانایی را بهبود می بخشد.
3). پارامترهای اختیاری را به خوبی مدیریت می کند
با سازنده ها، مقابله با پارامترهای اختیاری بدون استفاده از مقادیر تهی یا ایجاد بسیاری از سازنده های بارگذاری شده دشوار است.
Builder Pattern به شما امکان می دهد فقط پارامترهای مورد نیاز خود را بگنجانید، بدون اینکه نگران ارائه پیش فرض ها یا متغیرهایی برای هر پارامتر باشید.
بدون سازنده (با استفاده از سازنده):
const car = new Car(‘Tesla’, ‘Model S’, 2024, null, true, false); // Confusing
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
با سازنده:
const car = new CarBuilder(‘Tesla’, ‘Model S’)
.setYear(2024)
.addGPS()
.build(); // Clean and understandable
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
4). تغییر ناپذیری را ترویج می کند
هنگامی که شیء ساخته می شود، اغلب تغییر ناپذیر است—شما نمی توانید حالت آن را پس از ایجاد تغییر دهید. این تضمین می کند که شی ساخته شده در یک وضعیت معتبر و پایدار است و کد شما را ایمن تر و کمتر مستعد اشکال می کند.
مزیت: شی به طور کامل ساخته شده و پس از فراخوانی متد build() معتبر است و شانس خطاهای ناشی از اشیای نیمه ساخته شده را کاهش می دهد.
5). گسترش آسان تر
الگوی سازنده به راحتی قابل تمدید است. هنگامی که ویژگی ها یا ویژگی های جدید اضافه می شود، سازنده را می توان بدون تأثیر بر کد موجود تغییر داد.
بدون سازنده: اگر یک پارامتر جدید به سازنده اضافه کنید، باید هر نمونه از شی را در پایه کد تغییر دهید.
با بیلدر: شما به سادگی یک متد جدید تنظیم کننده را به سازنده اضافه می کنید، بدون اینکه روی مکان هایی که شی ساخته شده است تأثیری داشته باشید.
مثال: افزودن نوع موتور:
const car = new CarBuilder(‘Tesla’, ‘Model S’)
.setYear(2024)
.setColor(‘Red’)
.setEngineType(‘Electric’)
.build();
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
6). خوانایی و نگهداری بهبود یافته
Builder Pattern با تقسیم کردن فرآیند ساخت و ساز به مراحل کوچک و قابل درک، خوانایی بالایی ارائه می دهد.
این باعث میشود کد خود مستندتر شود—شما میتوانید به وضوح ببینید که یک شی چگونه ساخته میشود، بدون اینکه نیازی به جستجو کنید که هر آرگومان در سازنده چه چیزی را نشان میدهد.
مزیت: حفظ و تغییر کد آسان تر است زیرا هر روش به وضوح مشخص می کند که چه بخشی از شی را تغییر می دهد.
7). از ناسازگاری اشیاء جلوگیری می کند
Builder اطمینان حاصل می کند که تمام پارامترهای مورد نیاز قبل از ساخته شدن شی تنظیم شده است و از ایجاد اشیاء ناسازگار یا ناقص جلوگیری می کند.
این فرآیند اعتبارسنجی در زمان ساخت اتفاق میافتد و اطمینان حاصل میکند که شی در زمان ایجاد آن در وضعیت معتبری قرار دارد.
بدون سازنده: ممکن است اشیایی ایجاد کنید که ناقص یا به درستی مقداردهی اولیه شده باشند.
با بیلدر: الگوی سازنده یک شی سازگار و کاملاً ساخته را تضمین می کند.
8). نیاز به سازندگان بارگذاری شده را کاهش می دهد
بدون الگوی سازنده، ممکن است با چندین سازنده بارگذاری شده مواجه شوید تا ترکیبات مختلفی از پارامترها را در خود جای دهید.
مزیت: با سازنده، شما به چندین نسخه سازنده نیاز ندارید—فقط یک فرآیند ساختمانی واضح و انعطاف پذیر.
بیایید ایجاد شی را با و بدون الگوی سازنده با استفاده از یک مثال واقعی مقایسه کنیم، جایی که در حال ایجاد یک آبجکت خودرو هستیم که دارای چندین ویژگی است، که برخی از آنها اختیاری هستند.
بدون الگوی سازنده
1). استفاده از سازنده با پارامترهای زیاد
class Car {
constructor(make, model, year, color, hasGPS, hasSunroof) {
this.make = make;
this.model = model;
this.year = year;
this.color = color;
this.hasGPS = hasGPS || false; // Optional parameter
this.hasSunroof = hasSunroof || false; // Optional parameter
}
describe() {
return `${this.year} ${this.make} ${this.model} in ${this.color} color with GPS: ${this.hasGPS} and Sunroof: ${this.hasSunroof}`;
}
}
// Creating the object
const car = new Car(‘Tesla’, ‘Model S’, 2024, ‘Red’, true, false);
console.log(car.describe());
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
با الگوی سازنده
2). استفاده از الگوی سازنده
// Car class remains simple, no complex constructor
class Car {
constructor(builder) {
this.make = builder.make;
this.model = builder.model;
this.year = builder.year;
this.color = builder.color;
this.hasGPS = builder.hasGPS;
this.hasSunroof = builder.hasSunroof;
}
describe() {
return `${this.year} ${this.make} ${this.model} in ${this.color} color with GPS: ${this.hasGPS} and Sunroof: ${this.hasSunroof}`;
}
}
// CarBuilder class for step-by-step object creation
class CarBuilder {
constructor(make, model) {
this.make = make;
this.model = model;
}
setYear(year) {
this.year = year;
return this;
}
setColor(color) {
this.color = color;
return this;
}
addGPS() {
this.hasGPS = true;
return this;
}
addSunroof() {
this.hasSunroof = true;
return this;
}
build() {
return new Car(this); // Builds and returns the Car object
}
}
// Creating the object using the builder
const car = new CarBuilder(‘Tesla’, ‘Model S’)
.setYear(2024)
.setColor(‘Red’)
.addGPS()
.build();
console.log(car.describe());
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
من دوست دارم بشنوم که چگونه این ایده ها را در کار خود به کار برده اید؟ نظرات یا سوالات خود را در نظرات زیر به اشتراک بگذارید – مایلم از شما بشنوم.
از اینکه در این سفر آموزشی به من ملحق شدید متشکرم!
Builder Pattern یک الگوی طراحی خلاقانه است که راهی برای ساختن اشیاء پیچیده گام به گام ارائه می دهد. ساخت یک شی را از نمایش آن جدا می کند و به همان فرآیند ساخت اجازه می دهد تا انواع و نمایش های مختلفی از اشیاء را ایجاد کند.
حال این سوال پیش می آید که چرا به الگوی طراحی سازنده نیاز داریم، با چه مشکلی مواجه هستیم؟
در هنگام ایجاد شیء زمانی که شیء حاوی ویژگی های زیادی باشد، مشکلات زیادی وجود دارد:
- برای ایجاد شی باید آرگومان های زیادی را پاس کنیم
- برخی از پارامترها ممکن است اختیاری باشند
- کلاس کارخانه تمام مسئولیت ایجاد شی را بر عهده می گیرد. اگر جسم سنگین باشد، تمام پیچیدگی ها بخشی از کلاس کارخانه است
بنابراین در بیلدر پترن مزایای متعددی را به خصوص در هنگام ساخت اشیاء پیچیده ارائه می دهد و برای ایجاد گام به گام شیء و در نهایت برگرداندن شی با مقادیر مشخصه دلخواه استفاده می شود.
الگوی سازنده را می توان با یک تشبیه ساده توضیح داد: سفارش یک پیتزا سفارشی.
سناریوی بدون الگوی سازنده:
تصور کنید به یک پیتزا فروشی می روید و فقط یک گزینه برای سفارش پیتزا به شما داده می شود: باید همه چیز را یکجا مشخص کنید – نوع پوسته، اندازه، سس، رویه ها و مواد اضافی. اگر چیزی را نادیده گرفتید یا به اشتباه مشخص کردید، پیتزا 🍕 ممکن است آنطور که می خواهید پیش نیاید و باید کل فرآیند را از ابتدا دوباره انجام دهید. این مانند استفاده از سازنده ای با پارامترهای زیاد است – مستعد خطا و مدیریت آن دشوار است، به خصوص زمانی که گزینه ها یا موارد اختیاری زیادی وجود دارد.
مثال بدون سازنده:
“من یک پیتزا 🍕 با پوسته نازک، اندازه متوسط، سس گوجه فرنگی، قارچ، پنیر🧀، بدون زیتون🍅، و ریحان اضافه می خواهم.” اگر چیزی را از دست دادید، باید از نو شروع کنید!
سناریوی با الگوی سازنده:
اکنون، به یک رویکرد انعطافپذیرتر فکر کنید که در آن پیتزاساز گام به گام تنظیمات خود را از شما میخواهد:
ابتدا می پرسند چه سایزی می خواهید.
سپس در مورد نوع پوسته می پرسند.
در مرحله بعد، آنها در مورد تاپینگ ها می پرسند.
در نهایت، آنها از شما می پرسند که آیا چیزهای اضافی مانند پنیر اضافی یا سس خاصی می خواهید.
در هر مرحله بر اساس آنچه می خواهید تصمیم می گیرید و در انتها پیتزای کاملا متناسب با سلیقه خود دریافت می کنید. لازم نیست نگران به خاطر سپردن یا مشخص کردن همه چیز به یکباره باشید. هر انتخاب بر اساس انتخاب قبلی است.
مثال با بیلدر:
“من یک پیتزا متوسط می خواهم.”
“من پوسته نازک می خواهم.”
“قارچ و پنیر را اضافه کنید.”
“زیتون نه، لطفا.”
“ریحان اضافی اضافه کنید.”
Builder Pattern اجازه می دهد تا یک فرآیند گام به گام و ساختار یافته را انجام دهید، جایی که شما شی (یا پیتزا!) خود را به صورت تدریجی می سازید، که منجر به انعطاف پذیری بیشتر و اشتباهات کمتر می شود.
در اینجا چند نکته وجود دارد که مشاهده کردهام چگونه الگوی سازنده به شما برتری نسبت به سایر رویکردها مانند سازندههای تلسکوپ یا تنظیمکنندهها میدهد:
1). ساخت شی را با پارامترهای زیاد ساده می کند
- هنگامی که یک شی دارای پارامترهای اختیاری یا اجباری زیادی است، استفاده از یک سازنده استاندارد می تواند گیج کننده و مستعد خطا باشد.
- Builder Pattern یک رویکرد واضح و گام به گام برای ایجاد شی ارائه میدهد و تنظیم تنها ویژگیهای لازم را بدون نگرانی در مورد ترتیب پارامترها آسانتر میکند.
مثال: به جای این سازنده گیج کننده:
const car = new Car('Tesla', 'Model S', 2024, 'Red', true, false);
شما این کد قابل خواندن را دریافت می کنید:
const car = new CarBuilder('Tesla', 'Model S')
.setYear(2024)
.setColor('Red')
.addGPS()
.build();
2). پشتیبانی از رابط فلوئنت (زنجیره کردن روش)
- رابط روان به روشها اجازه میدهد تا خود شی سازنده را برگردانند و زنجیرهبندی متد را ممکن میسازد. این باعث میشود کد بصریتر و خواناتر باشد، زیرا یک فرآیند منطقی و گام به گام برای تنظیم ویژگیها ارائه میکند.
مزیت: هر فراخوانی متد مانند دنباله ای از دستورالعمل ها برای ساخت شی خوانده می شود و خوانایی را بهبود می بخشد.
3). پارامترهای اختیاری را به خوبی مدیریت می کند
- با سازنده ها، مقابله با پارامترهای اختیاری بدون استفاده از مقادیر تهی یا ایجاد بسیاری از سازنده های بارگذاری شده دشوار است.
- Builder Pattern به شما امکان می دهد فقط پارامترهای مورد نیاز خود را بگنجانید، بدون اینکه نگران ارائه پیش فرض ها یا متغیرهایی برای هر پارامتر باشید.
بدون سازنده (با استفاده از سازنده):
const car = new Car('Tesla', 'Model S', 2024, null, true, false); // Confusing
با سازنده:
const car = new CarBuilder('Tesla', 'Model S')
.setYear(2024)
.addGPS()
.build(); // Clean and understandable
4). تغییر ناپذیری را ترویج می کند
- هنگامی که شیء ساخته می شود، اغلب تغییر ناپذیر است—شما نمی توانید حالت آن را پس از ایجاد تغییر دهید. این تضمین می کند که شی ساخته شده در یک وضعیت معتبر و پایدار است و کد شما را ایمن تر و کمتر مستعد اشکال می کند.
مزیت: شی به طور کامل ساخته شده و پس از فراخوانی متد build() معتبر است و شانس خطاهای ناشی از اشیای نیمه ساخته شده را کاهش می دهد.
5). گسترش آسان تر
- الگوی سازنده به راحتی قابل تمدید است. هنگامی که ویژگی ها یا ویژگی های جدید اضافه می شود، سازنده را می توان بدون تأثیر بر کد موجود تغییر داد.
بدون سازنده: اگر یک پارامتر جدید به سازنده اضافه کنید، باید هر نمونه از شی را در پایه کد تغییر دهید.
با بیلدر: شما به سادگی یک متد جدید تنظیم کننده را به سازنده اضافه می کنید، بدون اینکه روی مکان هایی که شی ساخته شده است تأثیری داشته باشید.
مثال: افزودن نوع موتور:
const car = new CarBuilder('Tesla', 'Model S')
.setYear(2024)
.setColor('Red')
.setEngineType('Electric')
.build();
6). خوانایی و نگهداری بهبود یافته
- Builder Pattern با تقسیم کردن فرآیند ساخت و ساز به مراحل کوچک و قابل درک، خوانایی بالایی ارائه می دهد.
- این باعث میشود کد خود مستندتر شود—شما میتوانید به وضوح ببینید که یک شی چگونه ساخته میشود، بدون اینکه نیازی به جستجو کنید که هر آرگومان در سازنده چه چیزی را نشان میدهد.
مزیت: حفظ و تغییر کد آسان تر است زیرا هر روش به وضوح مشخص می کند که چه بخشی از شی را تغییر می دهد.
7). از ناسازگاری اشیاء جلوگیری می کند
- Builder اطمینان حاصل می کند که تمام پارامترهای مورد نیاز قبل از ساخته شدن شی تنظیم شده است و از ایجاد اشیاء ناسازگار یا ناقص جلوگیری می کند.
- این فرآیند اعتبارسنجی در زمان ساخت اتفاق میافتد و اطمینان حاصل میکند که شی در زمان ایجاد آن در وضعیت معتبری قرار دارد.
بدون سازنده: ممکن است اشیایی ایجاد کنید که ناقص یا به درستی مقداردهی اولیه شده باشند.
با بیلدر: الگوی سازنده یک شی سازگار و کاملاً ساخته را تضمین می کند.
8). نیاز به سازندگان بارگذاری شده را کاهش می دهد
- بدون الگوی سازنده، ممکن است با چندین سازنده بارگذاری شده مواجه شوید تا ترکیبات مختلفی از پارامترها را در خود جای دهید.
مزیت: با سازنده، شما به چندین نسخه سازنده نیاز ندارید—فقط یک فرآیند ساختمانی واضح و انعطاف پذیر.
بیایید ایجاد شی را با و بدون الگوی سازنده با استفاده از یک مثال واقعی مقایسه کنیم، جایی که در حال ایجاد یک آبجکت خودرو هستیم که دارای چندین ویژگی است، که برخی از آنها اختیاری هستند.
بدون الگوی سازنده
1). استفاده از سازنده با پارامترهای زیاد
class Car {
constructor(make, model, year, color, hasGPS, hasSunroof) {
this.make = make;
this.model = model;
this.year = year;
this.color = color;
this.hasGPS = hasGPS || false; // Optional parameter
this.hasSunroof = hasSunroof || false; // Optional parameter
}
describe() {
return `${this.year} ${this.make} ${this.model} in ${this.color} color with GPS: ${this.hasGPS} and Sunroof: ${this.hasSunroof}`;
}
}
// Creating the object
const car = new Car('Tesla', 'Model S', 2024, 'Red', true, false);
console.log(car.describe());
با الگوی سازنده
2). استفاده از الگوی سازنده
// Car class remains simple, no complex constructor
class Car {
constructor(builder) {
this.make = builder.make;
this.model = builder.model;
this.year = builder.year;
this.color = builder.color;
this.hasGPS = builder.hasGPS;
this.hasSunroof = builder.hasSunroof;
}
describe() {
return `${this.year} ${this.make} ${this.model} in ${this.color} color with GPS: ${this.hasGPS} and Sunroof: ${this.hasSunroof}`;
}
}
// CarBuilder class for step-by-step object creation
class CarBuilder {
constructor(make, model) {
this.make = make;
this.model = model;
}
setYear(year) {
this.year = year;
return this;
}
setColor(color) {
this.color = color;
return this;
}
addGPS() {
this.hasGPS = true;
return this;
}
addSunroof() {
this.hasSunroof = true;
return this;
}
build() {
return new Car(this); // Builds and returns the Car object
}
}
// Creating the object using the builder
const car = new CarBuilder('Tesla', 'Model S')
.setYear(2024)
.setColor('Red')
.addGPS()
.build();
console.log(car.describe());
من دوست دارم بشنوم که چگونه این ایده ها را در کار خود به کار برده اید؟ نظرات یا سوالات خود را در نظرات زیر به اشتراک بگذارید – مایلم از شما بشنوم.
از اینکه در این سفر آموزشی به من ملحق شدید متشکرم!