سلام دوستان! ساختن آبجکت‌ها همیشه به سادگی یک new کردن نیست. گاهی وقت‌ها ساختن یک آبجکت و آماده کردن اون برای استفاده، به پارامترها و ورودی‌های زیادی بستگی داره. برای مثال توی بیشتر زبان‌ها از Query Builder برای ساختن کوئری‌های SQL استفاده میشه:

const user = db.users.find(...);
// or
const post = db.posts.where(...).select(...).find(...);

همونطور که می‌بینیم آبجکت‌های user و post به ورودی‌های مختلفی نیاز دارن و طی چندین مرحله ساخته میشن.

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

 

الگوی Builder چیه؟

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

این الگو زیرمجموعه الگوهای Creational - الگوهایی که برای ساختن بهتر آبجکت‌ها استفاده میشه - هست. پیاده‌سازی این الگو خیلی راحته.

 

پیاده‌سازی الگوی Builder

فرض کنیم می‌خوایم یک Query Builder برای ساختن درخواست‌های SQL بسازیم. چیزی که می‌سازیم باید بتونه برای انواع دیتابیس‌ها مثل MySQL و MongoDB کارایی داشته باشه. به عبارت دیگه، برای کلاینت (قسمتی از برنامه که داره از این ویژگی استفاده می‌کنه) نباید مهم باشه که چه نوع دیتابیسی مورد استفاده قرار گرفته.

اولین راه پیاده‌سازی الگوی Builder اینه که مراحل مشترک ساختن آبجکت‌ها رو مشخص و تعریف کنیم. ابتدا یک اینترفیس می‌سازیم و این مراحل رو به صورت متد توی اون قرار می‌دیم:

interface QueryBuilder {
  table(table): QueryBuilder;
  select(cols): QueryBuilder;
  limit(): QueryBuilder;
  where(): QueryBuilder;
  getQuery(): String;
  
  /* +100 Other SQL Methods  */
}

توی Query Builder ها معمولاً متدهایی مثل where و limit و چندین دستور SQL داریم که اینجا به طور خلاصه ۴ تا از اونها رو تعریف کردیم. همچنین نوع خروجی همه متدها رو برابر با خودِ اینترفیس یعنی QueryBuilder قرار دادیم. این کار برای این هست که متدهای زیرکلاس‌ها رو مجبور کنیم با return this، خودِ کلاس رو return کنن تا بتونیم متدهای زنجیره‌ای (Method Chaining) داشته باشیم. یعنی:

obj.foo().bar().baz().blah().blah().blah();

 

مرحله بعد باید برای هر نوع دیتابیس یک کلاس اختصاصی بسازیم که از این اینترفیس تبعیت می‌کنن. ابتدا برای MySQL می‌نویسیم: