اینترفیس Fluent Builder به همراه Generic بازگشتی
شناسه پست: 3039
بازدید: 813

در پست قبلی، ما در مورد الگوهای طراحی Builder و Fluent Builder صحبت کردیم. بنابراین اگر با الگوی Fluent Builder آشنا نیستید، قبل از اینکه مطالعه این پست را ادامه دهید، به شدت توصیه میکنیم که پست قبلی را مطالعه کنید. در این پست، ما قصد داریم یک Fluent Builder را یک سطح بالاتر ببریم و نشان دهیم که در حالی که از Fluent Builder دیگری ارث بری میکنیم چگونه می توانیم از generic ها استفاده کنیم.

زمانیکه builder ها، از builder های دیگر ارث بری میکنند، هیچ اتفاق خاصی قرار نیست بیفتد و همه چیز باید به همان شکل باقی بماند. اما اگر یک Fluent Builder از یک Fluent Builder دیگر ارث بری کند، در اینصورت در مورد زنجیر کردن action ها به یکدیگر، به مشکل برخواهیم خورد. بنابراین قصد داریم برای فعال کردن رفتار پیشفرض اینترفیسهای fluent خود، از یک رویکرد Recursive Generics (Generic بازگشتی) استفاده کنیم.

این مقاله، بخشی از مجموعه آموزشی زیر است:

شما میتوانید سورس را از اینجا دانلود کنید: Fluent Builder به همراه Recursive Generics – سورس کد

برای مشاهده لیست کامل مقالات این مجموعه آموزشی، الگوهای طراحی #C را بررسی کنید.

این مقاله، به قسمتهای زیر تقسیم میشود:

مشکل با وراثت در Fluent Builder

تصور کنید که میخواهیم یک آبجکت Employee بسازیم. بنابراین بدیهی است که اولین کار، ایجاد کلاس model مان است:

در ادامه میخواهیم یک کلاس builder برای ساخت قسمت Name آبجکتمان ایجاد کنیم:

حالا میتوانیم کلاس builder  دیگری برای قسمت Position ایجاد کنیم و این کلاس قرار است که از کلاس EmployeeInfoBuilder  ارث بری کند، چرا که میخواهیم از آبجکت employee خود استفاده مجدد نماییم:

در نهایت، میتوانیم فراخونی ها را به سمت این کلاسهای builder انجام دهیم:

ینترفیس Fluent Builder به همراه Recursive Generics

اما همانطور که اینجا میبینید، ما قادر نیست آبجکت مورد نظر را ایجاد کنیم. این به این خاطر است که متد SetName، یک نمونه از نوع EmployeeInfoBuilder  را برمیگرداند که هم اکنون متد AtPosition راپیاده سازی نکرده و یا ارث بری نکرده است. این کاملا قابل درک است، چرا که کلاس EmployeeInfoBuilder، یک کلاس با order بالاتر است و کلاس EmployeePositionBuilder  از آن ارث بری میکند و بالعکس آن صحیح نیست.

بنابراین، ما باید راه حلی برای انتشار اطلاعات از کلاس مشتق شده به کلاس پایه پیدا کنیم و راه حل، اینجا، رویکرد generic بازگشتی است.

پیاده سازی Generic بازگشتی با Fluent Builder

بنابراین با کلاس EmployeeBuilder abstract شروع میکنیم که مسئول نمونه سازی و ارائه آبجکت employee میباشد:

زمانیکه این کلاس را ایجاد کردیم، در ادامه میتوانیم اطلاحات را در EmployeeInfoBuilder انجام دهیم. ما دیدم که SetName نمیتواند نوع EmployeeInfoBuilder را برگرداند. آن باید یک نوع generic  برگرداند. با توجه به این موضوع، بیایید کلاس خود را اصلاح کنیم:

خب. حالا این یعنی چی؟

خب، آنقدرها هم که در نگاه اول به نظر میرسد پیچیده نیست.

ما گفتیم که متد SetName، باید یکنوع generic برگرداند، بنابراین اینجا کلاس ما نیز generic میباشد. این کلاس باید از کلاس EmployeeBuilder  ارث بری کند، زیرا ما به آن آبجکت employee  نیاز داریم. در آخر، ما باید مطمئن شویم که type صحیحی را برای نوع T در کلاس خود دریافت میکنیم. برای این منظور، میتوانیم نوع T را به نوع EmployeeInfoBuilder محدود کنیم.

حالا میتوانیم کار خود را با اصلاح در EmployeePositionBuilder ادامه دهیم:

با این کار، ما وراثت را در هر دوی این کلاسها فعال ساخته ایم. آنها از رویکرد اینترفیس fluent builder پشتیبانی میکنند و حالا میتوانند نوع مورد نیاز را برگردانند.

این در سناریوی ما بسیار مفید است از آنجایی که کارمند ما به حقوق خود نیاز دارد، حالا به راحتی میتوانیم حقوق را با استفاده از متد WithSalary  در کلاس EmployeeSalaryBuilder اضافه کنیم:

در حال حاضر، ما میدانیم که چطور کلاسهای Builder را با generic بازگشتی بسازیم.

اما ما نمیتوانیم ساخت آبجکت خود را هنوز شروع کنیم.

این به این دلیل است که کاملاً مشخص نیست که هنگام ایجاد کلاس EmployeeInfoBuilder از چه نوعی باید استفاده کنیم.

بنابراین میخواهیم یک API ایجاد کنیم که امکان ساخت آبجکت را به ما بدهد:

حالا میتوانیم ساخت آبجکت خود را به شیوه fluent شروع کنیم:

عالی.

حالا ما میدانیم که چطور با استفاده از یک رویکرد generic بازگشتی، وراثت اینترفیس fluent را فعال کنیم.

نتیجه گیری

در مقاله بعدی، که قرار است دوباره به الگوی Builder مربوط شود، ما در مورد Faceted Builder صحبت می کنیم و نحوه استفاده از facade برای ایجاد یک آبجکت که به بیش از یک کلاس builder نیاز دارد را به شما نشان می دهیم.

نویسنده

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