از مشکلات تا راه حل ها: درک الگوهای طراحی
یک واقعیت جالب در توسعه نرم افزار این است که شما تقریبا همیشه اولین فردی نیستید که با مشکل خاصی روبرو می شوید. این مشکل ممکن است از ابتدای توسعه نرم افزار رخ داده باشد. در این پست وبلاگ، قصد داریم نگاهی به الگوهای طراحی، چرایی نیاز به آنها و مروری بر برخی از الگوهای طراحی بیاندازیم.
الگوهای طراحی یک رویکرد سیستماتیک برای رسیدگی به مشکلات تکراری است که برنامه نویسان با آن مواجه هستند. آنها یک استاندارد جهانی را برای حل آن مشکلات توصیف می کنند. راه حل ارائه شده به گونه ای است که می توان آن را با وجود دامنه خاص مشکل مورد استفاده مجدداً مورد استفاده قرار داد. بنابراین، دفعه بعد که با مشکل برنامه نویسی مواجه شدید، مراقب باشید که مجبور نباشید راه حل را دوباره از ابتدا کشف کنید.
چرا الگوهای طراحی؟
- تجربه یکی را کامل می کند: شما، به عنوان یک توسعه دهنده، باید ابتدا طرح های خوب موجود، حوزه کاربرد آنها و مبادلات را درک کنید تا بتوانید از آنها دوباره استفاده کنید یا طرح های خود را توسعه دهید.
- زبان مشترک طراحی: الگوهای طراحی واژگان مشترکی را برای برنامه نویسان فراهم می کند. این به برقراری ارتباط موثر با یکدیگر، کاهش سوء تفاهم ها و افزایش بهره وری کمک می کند.
- مقیاسپذیری بهتر: الگوهای طراحی به مقیاسپذیری بیشتر سیستمها کمک میکند و به آنها اجازه میدهد با تغییر نیازها رشد کرده و سازگار شوند.
- ساختار کد بهبودیافته: الگوهای طراحی به ساختار کد به شیوه ای سازگار و سازماندهی شده کمک می کند و درک و نگهداری آن را آسان تر می کند. این می تواند منجر به بهبود کیفیت کد و کاهش زمان توسعه شود.
عناصر یک الگوی طراحی
- نام – دسته ای است که برای توصیف مسئله طراحی استفاده می شود. ضروری است زیرا زمینه درک مشترکی را در بین برنامه نویسان ایجاد می کند.
- مسئله – برای توصیف زمانی که می توان از الگو استفاده کرد استفاده می شود.
- راه حل – الگویی است که عناصر و روابط آنها را بدون ارائه جزئیات پیاده سازی توصیف می کند.
- نتیجه – برای توصیف مبادلات الگو استفاده می شود. مثالها: معاوضههای زمانی و مکانی، انعطافپذیری، توسعهپذیری و غیره.
انواع الگوهای طراحی
الگوهای طراحی: عناصر نرم افزار شی گرا قابل استفاده مجدد، که معمولاً به نام باند چهار نفری، سنگ بنای مهندسی نرم افزار است که الگوهای طراحی را وارد جریان اصلی کرد. این کتاب 23 الگوی طراحی مختلف را که در 3 دسته زیر قرار می گیرند، تجزیه می کند:
- خلاقانه – آنها با تکنیک های خلق اشیا سروکار دارند.
- ساختاری – آنها با ترکیب اشیاء و کلاس ها به روشی انعطاف پذیر و مؤثر سروکار دارند.
- رفتاری – آنها به تعامل بین کلاس ها و اشیا و مسئولیت آنها می پردازند.
مقدمه ای بر شش الگوی طراحی
بخش زیر قصد دارد یک نمای کلی از 6 الگوی طراحی نرم افزار (2 الگو از هر دسته) و نحوه استفاده از آنها برای حل چالش های رایج برنامه نویسی ارائه دهد.
1. سینگلتون
الگوی Singleton نوعی الگوی ایجادی است که ایجاد یک نمونه واحد از یک کلاس را تضمین می کند و یک نقطه دسترسی جهانی به آن نمونه را فراهم می کند.
چرا:
فرض کنید در حال ساخت یک کلاس اتصال پایگاه داده هستید:
- شما نمی خواهید برای هر شیئی که نیاز به دسترسی به آن دارد یک نمونه DB جداگانه ایجاد کنید. اگر این کار را انجام دهید، هزینه بالایی خواهد داشت. این مفهوم برای سایر منابع مشترک مانند فایل ها نیز صدق می کند.
- شما می خواهید دسترسی جهانی و آسان به آن نمونه فراهم کنید. شبیه به متغیرهای سراسری، الگوی Singleton به شما امکان دسترسی به یک شی از هر نقطه در برنامه را می دهد.
چگونه:
راه های مختلفی برای پیاده سازی الگوی Singleton وجود دارد. با این حال، همه پیاده سازی ها مفاهیم اساسی زیر را به اشتراک می گذارند:
- برخلاف یک سازنده معمولی که هر زمان که یک شی جدید را فراخوانی می کنید، یک کلاس Singleton دارای a است سازنده خصوصی یک سازنده خصوصی از نمونه سازی شی از کلاس Singleton توسط سایر اشیاء جلوگیری می کند.
- یک متغیر نمونه خصوصی
- یک روش ایستا که ارجاع به آن نمونه را برمی گرداند. این روش استاتیک اساساً به عنوان سازنده عمل میکند و سازنده خصوصی را در زیر هود فرا میخواند تا یا یک شی (در صورت درخواست برای اولین بار) ایجاد کند یا آن را در حافظه پنهان (برای درخواستهای بعدی) برگرداند.
2. روش کارخانه
روش کارخانه نیز نوع دیگری از الگوی ایجاد است که یک رابط برای ایجاد اشیا فراهم میکند، اما به کلاسهای فرعی اجازه میدهد تصمیم بگیرند که کدام کلاس را نمونهسازی کنند. به عبارت دیگر، کلاس های فرعی می توانند نوع اشیایی که ایجاد می شوند را تغییر دهند.
چرا:
فرض کنید در حال ایجاد یک چارچوب گزارش با استفاده از الگوی طراحی روش کارخانه برای ثبت انواع مختلف پیامها از جمله پیامهای خطا، پیامهای هشدار و پیامهای اطلاعاتی هستید. در این مورد استفاده:
- لاگر می تواند یک روش کارخانه ای برای ایجاد انواع مختلف پیام ها ارائه دهد.
- کد سرویس گیرنده ای که از این لاگر استفاده می کند نیازی به دانستن اجرای دقیق پیام ها ندارد، فقط باید رابط کاربری ایجاد آنها را بداند.
- شما می توانید انعطاف پذیری را فراهم کنید. اگر فرآیند ایجاد شی تغییر کند، مثلاً یک کلاس جدید اضافه شود، فقط باید روش کارخانه به روز شود. نیازی به تغییر کد مشتری که از آن اشیا استفاده می کند نیست.
چگونه:
- فراخوانی های ساخت مستقیم شی را با فراخوانی به روش کارخانه ای خاص جایگزین کنید.
- به جای فراخوانی سازنده، یک شی را با فراخوانی متد کارخانه ایجاد کنید.
3. آداپتور
آداپتور نوعی الگوی طراحی ساختاری است که به اشیا با رابط های ناسازگار اجازه می دهد با هم کار کنند. در یک موقعیت واسطه بین مشتری و رابطی قرار دارد که مشتری می خواهد با آن ارتباط برقرار کند.
چرا:
فرض کنید با پیروی از الگوی طراحی آداپتور در حال ساخت یک ابزار تبدیل فرمت ویدیو هستید:
- نرم افزار شما باید بین فرمت های ویدئویی مختلف مانند MP4، AVI و FLV سازگار شود. باید بتواند ویدیویی را با هر فرمتی به عنوان ورودی بگیرد و آن را به فرمت دلخواه تبدیل کند. ارتباط بین هدف و مشتری از طریق آداپتور انجام می شود.
- اگر در آینده میخواهید از فرمتهای جدید پشتیبانی کنید، این الگو کار را آسانتر میکند زیرا تبدیل فرمت ویدیو از فرمتهای ویدیویی خاص جدا شده است.
چگونه:
- یک کلاس آداپتور تعریف کنید که رابط ناسازگار یک کلاس (تطبیق دهنده) را به رابط دیگر (هدف) مورد انتظار مشتریان تبدیل کند.
- از این آداپتور برای کار با (استفاده مجدد) کلاس های دیگر که رابط مورد نیاز را ندارند استفاده کنید.
4. دکوراتور
دکوراتور نوع دیگری از الگوهای طراحی سازه است که به شما امکان می دهد رفتارهای جدیدی را به اشیاء متصل کنید بدون اینکه بر رفتار سایر اشیاء از همان کلاس تأثیر بگذارد. حتی اگر از وراثت می توان برای تغییر رفتار یک شی به صورت ایستا استفاده کرد، یک دکوراتور به شما کمک می کند تا آن را به صورت پویا نیز تغییر دهید.
چرا:
فرض کنید در حال ساخت یک ویرایشگر متن هستید:
- ویرایشگر متن میتواند جزء ملموس شما باشد و یک غلطگیر املا میتواند تزئین کننده شما باشد.
- کلاس غلطگیر املا باید رابطی مشابه با کلاس ویرایشگر متن داشته باشد تا بتوان از آن به عنوان دکوراتور استفاده کرد.
- کلاس غلطگیر املا میتواند ویرایشگر متن را بپیچد و قابلیت غلطگیری املا را به ویرایشگر اضافه کند. این باعث می شود در آینده قابلیت های جدیدی به ویرایشگر اضافه شود.
چگونه:
- یک رابط برای اجزا و دکوراتورها تعریف کنید.
- اجزای بتنی و دکوراتورهای بتنی را که با رابط مطابقت دارند اجرا کنید.
- دکوراتورها باید به اجزایی که تزیین می کنند اشاره داشته باشند و برای انجام رفتارهای اساسی به اجزاء تفویض کنند. دکوراتورها روش هایی خواهند داشت که رفتار جدیدی را اضافه می کند.
- از دکوراتورها استفاده کنید تا اجزا را به ترتیب دلخواه بپیچید تا رفتار اضافی را به هم بچسبانید.
توجه داشته باشید – آداپتور رابط متفاوتی را برای موضوع خود فراهم می کند. Decorator یک رابط پیشرفته ارائه می دهد.
5. ناظر
مشاهدهگر یک الگوی طراحی رفتاری است که وابستگی یک به چند را بین اشیا تعریف میکند، به طوری که وقتی یک شی، به نام موضوع، وضعیت خود را تغییر می دهد، تمام وابسته های آن، نامگذاری شده است ناظران، به طور خودکار مطلع و به روز می شوند.
چرا
فرض کنید در حال ساخت یک وب سایت بورس هستید:
- می توانید از الگوی Observer برای به روز رسانی کاربران خود با آخرین قیمت سهام استفاده کنید.
- وب سایت موضوع است و کاربران آن ناظران هستند. هر زمان که قیمت سهام تغییر کند، وب سایت به کاربران خود اطلاع می دهد.
چگونه
- یک شی موضوع را تعریف کنید.
- اشیاء Observer را تعریف کنید. یک ناظر می تواند در جریانی از رویدادها اشتراک یا لغو اشتراک کند.
- رابطه بین سوژه و ناظران نباید محکم باشد.
- هنگامی که وضعیت سوژه تغییر می کند، همه ناظران ثبت نام شده مطلع و به روز می شوند.
6. استراتژی
استراتژی نوع دیگری از الگوی طراحی رفتاری است که به شما امکان می دهد خانواده ای از الگوریتم ها را تعریف کنید، هر کدام را کپسوله کنید و آنها را قابل تعویض کنید. مشتری را قادر می سازد تا رفتار الگوریتم را در زمان اجرا انتخاب کند.
چرا
فرض کنید در حال ایجاد نرم افزاری هستید که دارای قابلیت مرتب سازی است:
- یک الگوریتم مرتبسازی مانند مرتبسازی سریع، مرتبسازی درج یا مرتبسازی حبابی را میتوان در زمان اجرا انتخاب کرد و برای مرتبسازی مجموعهای از موارد استفاده کرد.
- استراتژیهای مرتبسازی را میتوان به راحتی جایگزین یا اصلاح کرد، که امکان افزودن یا حذف عملکرد در صورت نیاز را ممکن میسازد
چگونه
- یک رابط استراتژی ایجاد کنید که رفتار مشترک را تعریف کند.
- کلاس های استراتژی مشخصی ایجاد کنید که با رابط استراتژی مطابقت داشته باشد. هر استراتژی بتن، تنوعی از الگوریتم است.
- یک کلاس زمینه ایجاد کنید که ارجاع به یک شی استراتژی مرتب سازی را تعریف کند.
- کلاس context باید متدی داشته باشد که یک شی استراتژی را بپذیرد و استراتژی انتخاب شده را فراخوانی کند.
نتیجه
در نتیجه، داشتن درک کامل از الگوهای طراحی بسیار مهم است، به ویژه هنگامی که حرفه خود را در مهندسی نرم افزار پیش می برید.
ارجاع
https://www.amazon.com/gp/product/0201633612/
https://refactoring.guru/