Design Pattern چیست؟
«نسخه کامل و جامع این مقاله به همراه جزئیات بیشتر، در imaniNova.ir منتشر شده است. در ادامه قطعه ای از این مقاله را مشاهده می کنید.»
دیزاین پترن (Design Pattern) یا الگوی طراحی، یک تکه کد آماده یا یک کتابخانه قابل دانلود برای کپی پست کردن در پروژه نیست؛ بلکه یک نقشه راه انتزاعی، فرموله شده و تست شده برای حل چالش های ساختاری و تکراری است که معماران نرم افزار در طول تاریخ توسعه سیستم های شیء گرا (OOD) با آن ها مواجه شده اند. به زبان ساده، وقتی هزاران برنامه نویس در سراسر جهان در مواجهه با یک مشکل ساختاری به یک راهکار بهینه و مشترک می رسند، آن راهکار استانداردسازی شده و نام یک «دیزاین پترن» را به خود می گیرد تا زبان مشترکی میان مهندسان ایجاد کند.
برخلاف تصور عموم که دیزاین پترن ها را صرفا به الگوهای کلاسیک لایه کدنویسی محدود می کنند، تفکر الگومحور در تمام چرخه حیات نرم افزار جریان دارد. در ادامه، کاربرد پترن ها را در پنج سطح استراتژیک—از فاز انتزاعی طراحی و مدل سازی دمین تا پایگاه داده و معماری کلان سیستم—به طور کامل و با جزییات دقیق بسط می دهیم.
بعد اول: فاز طراحی و مدل سازی دمین (Domain Modeling)پیش از آنکه محیط توسعه (IDE) باز شود یا ساختار جداول دیتابیس شکل بگیرد، معمار سیستم باید منطق، قوانین بیزینس و روابط میان مفاهیم دمین را مدل سازی کند. پترن های این لایه وظیفه دارند فرآیندهای پیچیده دنیای واقعی را به ساختارهای انتزاعی قابل فهم برای نرم افزار تبدیل کنند، بدون اینکه به زبان برنامه نویسی یا فریم ورک خاصی وابسته باشند.
- ۱. الگوی وضعیت (State Pattern)
- کاربرد: این الگو زمانی به کار می رود که یک موجودیت بیزینسی (مانند فاکتور مالی، سفارش خرید یا تیکت پشتیبانی) دارای یک چرخه حیات مشخص با چندین وضعیت مختلف است و رفتار آن موجودیت بسته به وضعیتی که در آن قرار دارد، به طور کامل تغییر می کند. در رویکرد سنتی، برنامه نویسان برای مدیریت رفتارهای مختلف در وضعیت های مختلف، به سراغ بدنه های طولانی و پر از شرط های تودرتوی if-el
se یا switchهای غول آسا می روند. این ساختار با اضافه شدن یک وضعیت جدید بیزینسی کاملا می شکند و ریسک بروز باگ را به شدت بالا می برد. پترن State با تبدیل هر وضعیت به یک کلاس مستقل، این چالش را حل می کند. در واقع به جای اینکه شیء اصلی مدام بررسی کند که در چه وضعیتی است، رفتار خود را به کلاس وضعیت فعلی خود واگذار (Delegate) می کند. - مثال : چرخه حیات یک سفارش را در یک سیستم e-commerce بزرگ در نظر بگیرید. این سفارش حالت های
ثبت اولیه،پرداخت شده،در حال بسته بندی،ارسال شدهوتحویل داده شدهرا طی می کند. متدهایی مانندCancelOrder()(لغو سفارش) یاRefundMoney()(برگشت وجه) در هر کدام از این وضعیت ها رفتارهای متفاوتی دارند. اگر کاربر در وضعیتارسال شدهدرخواست لغو سفارش دهد، سیستم باید خطا بازگرداند؛ اما همین درخواست در وضعیتثبت اولیهکاملا مجاز است. با پیاده سازی پترن State، هر حالت یک کلاس مستقل است که قوانین همان وضعیت را پیاده سازی می کند. اگر بیزینس تصمیم بگیرد وضعیت جدیدی به نام «مفقود شده در پست» اضافه کند، معمار سیستم بدون دست زدن به کدهای وضعیت های قبلی، یک کلاس جدید می سازد و منطق آن را پیاده سازی می کند.
۲. الگوی شیء مقدار (Value Object Pattern)
- کاربرد: این الگو که از مفاهیم کلیدی طراحی دامنه-محور (DDD) در فاز مدل سازی است، به اشیائی اشاره دارد که برخلاف موجودیت ها (Entities)، فاقد هرگونه شناسه یکتا (مثل Id) هستند. هویت یک شیء مقدار، صرفا و الزما وابسته به «مقادیری» است که در خود نگه می دارد. یکی از ویژگی های حیاتی این پترن، تغییرناپذیری (Immutability) است؛ به این معنی که این اشیاء پس از نمونه سازی، هرگز قابل تغییر نیستند. اگر نیاز به تغییر فیلدی باشد، باید کل شیء از بین رفته و یک شیء جدید با مقادیر جدید ساخته شود. این کار پایداری داده ها را در تمام طول اجرای برنامه تضمین می کند.
- مثال : مفهوم «مبلغ مالی» یا «آدرس» بهترین نمونه ها هستند. یک مبلغ مالی از دو بخش تشکیل شده است: عدد مقدار (مثلا ۵۰۰,۰۰۰) و واحد پولی (مثلا تومان). اگر دو شیء مجزا در دو بخش مختلف سیستم با مقدار ۵۰۰,۰۰۰ تومان داشته باشیم، از نظر بیزینس این دو کاملا با هم برابر هستند و هیچ شناسه یا هویت جداگانه ای ندارند. مدل کردن این مفهوم به صورت یک Value Object باعث می شود که تمام قوانین اعتبارسنجی (مانند اینکه واحد پولی نمی تواند خالی باشد یا مبلغ نمی تواند منفی باشد) دقیقا در کپسول زمان ساخت شیء اجرا شود. این الگوی طراحی مانع از ورود دیتای فاسد یا نامعتبر به لایه های درونی سیستم می شود.
این لایه، همان بستر کلاسیک و شناخته شده پترن هاست؛ جایی که کلاس ها، رابط ها (Interfaces) و اشیاء در محیط کدنویسی با یکدیگر تعامل می کنند. تمرکز این بعد روی مدیریت حافظه، کاهش وابستگی های مستقیم کدهای بک اند و افزایش قابلیت تست نویسی واحد است.
۱. الگوی واسط (Mediator Pattern)
- کاربرد: در پروژه های بزرگ و پیچیده، اگر کلاس های مختلف بیزینس بخواهند به طور مستقیم با یکدیگر ارتباط برقرار کنند و متدهای یکدیگر را صدا بزنند، شبکه درهم تنیده ای از وابستگی های شدید (Tightly Coupled) شکل می گیرد. در این حالت، تغییر دادن یا تست کردن یک کلاس، مستلزم ساخت نمونه از ده ها کلاس دیگر است. پترن Mediator با معرفی یک شیء واسط مرکزی، این ارتباطات مستقیم را کاملا قطع می کند. کلاس ها (که به آن ها Colleague گفته می شود) دیگر هیچ شناختی از وجود یکدیگر ندارند؛ آن ها پیام یا درخواست خود را به واسط مرکزی می فرستند و واسط وظیفه دارد آن درخواست را به دست گیرنده یا پردازش کننده مناسب برساند.
- مثال: در پروژه های مدرن بک اند، این پترن معمولا با کتابخانه هایی مثل MediatR پیاده سازی می شود. فرض کنید یک درخواست API برای «ثبت نام کاربر جدید» به سیستم می رسد. در حالت عادی، کنترلر شما باید به کلاس سیستم دیتابیس، کلاس ارسال ایمیل خوش آمدگویی و کلاس سیستم امتیازدهی وابسته باشد. با استفاده از پترن Mediator، کنترلر شما تنها و تنها به اینترفیس IMedi
ator وابسته می شود. کنترلر یک شیء به نام RegisterUserCommand را به واسط تحویل می دهد و واسط به طور خودکار Handler مربوط به آن را پیدا و اجرا می کند. با این کار، لایه کنترلر یا کلاینت کاملا سبک شده و تست کردن آن بسیار ساده می شود.
۲. الگوی استراتژی (Strategy Pattern)
- کاربرد: این پترن خانواده ای از الگوریتم ها یا رفتارهای هم خانواده را تعریف کرده، هر کدام را در یک کلاس مجزا کپسوله می سازد و آن ها را در زمان اجرا (Runtime) به صورت داینامیک قابل تعویض می کند. این الگو تجسم عینی اصل Open/Closed Principle (OCP) از اصول SOLID است؛ چرا که سیستم را برای توسعه باز و برای تغییر می بندد. شما بدون دست زدن به کدهای اصلی سیستم، می توانید رفتار جدیدی را به برنامه تزریق کنید.
- مثال: سیستم محاسبه هزینه ارسال یا درگاه های پرداخت در یک پلتفرم فروشگاهی را در نظر بگیرید. بیزینس نیاز دارد که کاربر بتواند بین روش های ارسال «پست پیشتاز»، «پیک موتوری» و «باربری» یکی را انتخاب کند. منطق محاسبه قیمت برای هر کدام کاملا متفاوت است. به جای نوشتن یک کلاس بزرگ با جملات شرطی if ط
ولانی که نگهداری آن کابوس است، یک اینترفیس به نام IShippingStrategy تعریف می شود و برای هر روش ارسال، یک کلاس مستقل (مانند ExpressShippingStrategy) ساخته می شود. در زمان اجرا، سیستم بر اساس انتخاب کاربر، استراتژی مناسب را تزریق کرده و متد محاسبه قیمت را صدا می زند. اضافه کردن یک روش ارسال جدید، صرفا یعنی ساختن یک کلاس جدید، بدون نیاز به تغییر دادن کدهای قبلی. - ادامه مقاله در
- https://imaninova.ir/ArticleView?what-is-design-pattern-and-its-applications