دیزاین پترن چیست ؟ – به زبان ساده + اهمیت و کاربرد – فرادرس

دیزاین پترن چیست ؟ – به زبان ساده + اهمیت و کاربرد – فرادرس


«دیزاین پترن» (Design Pattern)، یکی از مفاهیم مهم و محبوب در بین توسعه‌دهندگان نرم‌افزار محسوب می‌شود. این «الگوهای طراحی» در واقع، راهکارهایی صریح برای مسائل رایج در فرایند طراحی پروژه‌های نرم‌افزاری به‌شمار می‌روند. دیزاین پترن‌ها با ارائه رویکردی مناسب برای حل مشکلات خاص، برنامه‌نویسان را در مواردی همچون کارآمدی، قابلیت نگهداری و مقیاس‌پذیری کدهایشان یاری می‌دهند. با وجود اینکه این الگوها، راه‌حل کاملی را برایمان فراهم نمی‌کنند اما اصول و طرح‌هایی در اختیارمان قرار می‌دهند که می‌توانند در توسعه پروژه نرم‌افزاری مورد استفاده قرار گیرند. در این مطلب از مجله فرادرس یاد می‌گیریم که دیزاین پترن چیست و همچنین با انواع الگوهای طراحی موجود آشنا شویم.

در این نوشتار می‌خواهیم مجموعه‌ای از دیزاین پترن‌های معرفی شده به‌وسیله «Gangs of Four» در کتاب «دیزاین پترن‌ها: مؤلفه‌های نرم‌افزار شی‌گرا با قابلیت استفاده مجدد» (Design Patterns: Elements of Reusable Object-Oriented Software) را با هم مرور کنیم. این کتاب، که یکی از محبوب‌ترین منابع چاپی برای آشنایی و یادگیری دیزاین پترن‌ها محسوب می‌شود، اولین بار در سال ۱۳۷۳ (۱۹۹۴ میلادی) منتشر شد. دلیل لقب گرفتن این کتاب به «Gangs of Four Design Patterns» یا «GoF Design Patterns»، این است که به‌وسیله ۴ نویسنده یعنی «اریش گاما»، «ریچارد هلم»، «رالف جانسون» و «جان ولیسایدز» نوشته شده است.

برای مشاهده تصویر در ابعاد بزرگتر، روی آن کلیک کنید.

دیزاین پترن‌ها، به ما کمک می‌کنند تا طراحی نرم‌افزار به گونه‌ای انجام شود که علاوه بر منعطف بودن، قابل استفاده مجدد و نگهداری نیز باشد. با پیروی از الگوهای توضیح داده شده در کتاب «الگوهای طراحی: عناصر نرم افزار شی‌گرا با قابلیت استفاده مجدد»، توسعه دهندگان می‌توانند نرم‌افزارهایی بسازند که درک و اصلاح آن آسان باشد، همچنین علاوه بر اینکه ریسک وجود باگ را کاهش می‌دهند، افزودن «ویژگی‌های» (Features) جدید به نرم‌افزار را نیز آسان‌تر می‌کنند.

دیزاین پترن چیست؟

دیزاین پترن‌های نرم‌افزاری، راهکارهایی با قابلیت استفاده مجدد برای مقابله با مشکلات توسعه نرم‌افزار هستند. با این وجود، «دیزاین پترن نرم‌افزار» کدهای نرم‌افزاری نیستند، بلکه راهنما یا «الگویی» (Paradigm) است که به مهندسان نرم‌افزار کمک می‌کند تا محصولات خود را مطابق با بهترین شیوه‌ها ایجاد کنند. به بیان ساده‌تر، دیزاین پترن را می‌توانیم الگویی برای مقابله با مسئله فعلی در نظر بگیریم تا اینکه «کتابخانه» (Library) یا «فریمورکی» (Framework) باشد که می‌تواند بلافاصله اضافه شود مورد استفاده قرار گیرد.

دیزاین پترن‌ها، از «برنامه‌نویسی شی‌گرا» (Object-Oriented Programming | OOP) – که بر اساس ایده‌‌ای از «اشیا» (Objects) و «کلاس‌ها» (Classes) هستند – پشتیبانی می‌کنند. دیزاین پترن‌ها، نقشه‌هایی هستند که برای حل مسائل معمولِ مهندسی نرم‌افزار به‌کار می‌روند. این الگوها یا پترن‌ها، برای برخی از متداول‌ترین مشکلاتی که با آن رو‌به‌رو می‌شویم، راهکارهایی «تکرارپذیر» (Reproducible) – هنگام وقوع مسائل مشابه – ارائه می‌دهند.

با همه این تفاسیر، دیزاین پترن‌ها راه‌حلِ کامل محسوب نمی‌شوند. یعنی شامل کدهای برنامه، کلاس‌ها یا کتابخانه‌هایی نیستند که بتوانیم به طور مستقیم در پروژه‌هایمان استفاده کنیم. بلکه نوعی راهکار برای حل مسئله مشخص به‌شمار می‌روند.

پیش نیاز یادگیری دیزاین پترن چیست ؟

برای آشنایی و یادگیری دیزاین پترن‌ها لازم است تا با مقدمات برنامه‌ نویسی شی‌گرا، از جمله «وراثت» (Inheritance)، «کپسوله‌سازی» (Encapsulation)، پلی مورفیسم یا «چندریختی» (Polymorphism)، اینترفیس‌ها یا «رابط‌ها» (Interfaces)، «کلاس‌های انتزاعی» (Abstract Classes)، «مِتُدهای مجازی» (Virtual Methods)، «رونویسی» (Overriding)، «سربارگزاری» (Overloading) و موارد این چنینی آشنایی نسبی داشته باشیم.

به‌طورکلی، می‌توان گفت که «دیزاین پترن‌ها»، مجموعه‌ای از راه‌حل‌های عمومی برای مسائلی هستند که به دفعات در فرایند توسعه نرم‌افزارهای شی‌گرا رخ می‌دهند. این راه‌حل‌های اثبات شده برای مسائل خاص، در طول سال‌ها آزمون و خطا به‌وسیله برنامه‌نویسان با تجربه به‌دست آمده‌اند.

درک این نکته مهم است که دیزاین پترن‌ها، صرفاٌ راه‌حل‌هایی معمولی برای مشکلات نیستند، بلکه «راه‌حل‌های الگویی» (Template-Solutions) هستند که می‌توانند بر اساس مسئله مورد نظر ما اصلاح و سفارشی شوند. به بیان دیگر، هر دیزاین پترن را می‌توان طرحی در نظر گرفت که می‌تواند برای حل یک مشکل طراحی خاص به‌کار گرفته شود. همچنین می‌توان آن را در هر ماژول – بخش – نرم‌افزاری و در هر مرحله از توسعه مورد استفاده قرار داد. دیزاین پترن‌ها، راهبردهایی «مستقل از زبان» (Language-Independent) هستند که ویژگی‌های مانند «انعطاف‌پذیری»، «قابلیت نگهداری» و «قابلیت استفاده مجدد» را برای کدهایمان فراهم می‌کند. بنابراین، الگوهای طراحی به کدهای نوشته شده به یک زبان برنامه‌نویسی خاص اشاره ندارند، بلکه هنگام پیاده‌سازی برنامه، در قالب کدهایی نوشته می‌شوند.

دلیل نیاز ما به دیزاین پترن چیست؟

به دلایلی که در ادامه آورده‌ایم، به دیزاین پترن‌های معماری نرم‌افزار نیازمندیم و استفاده از آن‌ها می‌تواند برایمان سودمند باشد.

  • «افزایش قابلیت نگهداری کدهای برنامه» (Enhance Code Maintainability): دیزاین پترن‌ها به ماژولار و ساخت‌یافته شدن کدها کمک می‌کنند.در نتیجه، سهولت در «نگهداری» (Maintain)، اصلاح یا «تغییر» (Modify) و گسترش – به هنگام تغییر نیازها – کدها را به‌دنبال خواهد داشت.
  • بهبود «قابلیت استفاده مجدد» (Reusability | تکرارپذیری) کدها: با توجه به‌اینکه دیزاین پترن‌ها راهکارهایی با قابلیت استفاده مجدد را برای مسائل و مشکلات رایج فراهم می‌کنند، توسعه‌ٰدهندگان می‌توانند با به‌کارگیری مجدد از راه‌حل‌های اثبات شده – یا به اصصطلاح به‌جای اختراع دوباره چرخ- در زمان و انرژی خود، صرفه‌جویی کنند.
  • درک و یادگیری دیزاین پترن‌ها اهمیت زیادی دارد حتی اگر قصد به‌کار بستن آن‌ها را نداشته باشیم. آشنایی و آگاهی داشتن از دیزاین پترن‌ها – همان الگوهای طراحی – می‌تواند در اتخاذ تصمیم‌های مربوط به معماری نرم‌افزار و همچنین درک و بررسی کدهای موجود، کمک کند.
  • ترویج بهترین روش‌ها (Best Practices): الگوهای طراحی، بهترین روش‌ها و اصول را در بر می‌گیرند که می‌تواند تولید سیستم‌های نرم‌افزاری سودمند، بهینه و همچنین مقیاس‌پذیرتر را به‌دنبال داشته باشد.
  • «تسهیل مشارکت و کار تیمی» (Facilitate Collaboration): دیزاین پترن‌ها، زبانی مشترک برای بحث، «ارزیابی» (Evaluate) و توافق در مورد تصمیم‌های مربوط به طراحی نرم‌افزار فراهم می‌‌کنند که مشارکت و همکاری بین اعضای تیم‌ها را آسان‌تر می‌کنند.

دیزاین پترن‌ها برای حل مشکلات رایج در نظر گرفته شده است، یعنی مسائلی که به بارها و بارها با آن‌ها روبه‌رو می‌شویم و الزامی مبنی بر اینکه همیشه از دیزاین پترن‌ها در پروژه‌هایمان استفاده کنیم وجود ندارد. زیرا هدف از این الگوها توسعه پروژه نیست، بلکه راه‌حل‌هایی برای مشکلات خاص عرضه می‌کنند. هر زمانی‌که نیاز بود، می‌توانیم پترن مناسبی را (با توجه به مشکل)، پیاده‌سازی تا از بروز چنین مشکلی در آینده جلوگیری کنیم. برای تشخیص اینکه از کدام الگو باید استفاده کنیم، می‌بایست دیزاین پترن‌ها و اهدافی که دارند را به‌خوبی درک کنیم. تنها از این طریق است که می‌توانیم مورد مناسب را برای پروژه خود بر گزینیم.

بنابراین، برای به‌کارگیری دیزاین پترن مناسب در پروژه‌هایمان، لازم است تا هدف و کاربرد هر یک از این دیزاین پترن‌ها را درک کرده باشیم.

مثالی از کاربرد دیزاین پترن ها

در این‌جا چندین نمونه از کاربردهای دیزاین پترن‌ها در دنیای واقعی را بیان می‌کنیم. برای مورد اول، «رئیس جمهور» یک کشور را نظر می‌گیریم. بدیهی است که در یک زمان مشخص تنها یک نمونه از آن – یک رئیس جمهور – می‌تواند – و باید – برای کشور مورد نظر وجود داشته باشد. در حقیقت این مثال، یکی از مواردی است که می‌خواهیم تنها یک نمونه از یک «کلاس» موجود باشد. پترنی که در دنیای توسعه نرم‌افزار این کار را برای ما انجام می‌دهد، «سینگلتون» نام دارد.

نمونه‌ای از آن می‌تواند «اتصال یگانه پایگاه داده» (Single DB Connection) باشد. به این دلیل که ایجاد «اتصالِ پایگاه داده» به‌طور مجزا برای هر یک از آبجکت‌ها، هزینه‌بر است، می‌توانیم یک نمونه از آن داشته باشیم – بسازیم – به‌طوری‌که بین اشیا متعددی به اشتراک گذاشته شده است. به‌همین ترتیب در مثالی دیگر، در یک اپلیکیشن، می‌توانیم تنها یک «مدیر پیکربندی» (Configuration Manager) یا «مدیر خطا» (Error Manager) داشته باشیم که به‌جای ایجاد چندین مدیر، به تمامی‌مشکلات رسیدگی می‌کند.

مزایای استفاده از دیزاین پترن چیست؟

در ادامه، برخی از مزیت‌های استفاده از دیزاین پترن‌های نرم‌افزاری را بیان کرده‌ایم.

  • «سرعت بخشیدن به توسعه» (Accelerated Development): دیزاین پترن‌ها راهکارهای اثبات ‌شده‌ای را دراختیارمان قرار می‌دهند که به فرایند توسعه برنامه نرم‌افزاری سرعت می‌بخشد و زمان صرف شده برای «حل مسائل پیچیده از ابتدا» را کاهش می‌دهد.
  • «بهبود کیفیت کدها» (Enhanced Code Quality): با پیروی از دیزاین پترن‌ها، برنامه‌نویسان می‌توانند کدهای بهتر – قوی‌تر و بهینه‌تر – و همچنین قابل اعتمادتری داشته باشند که دربرگیرنده‌ی «بهترین روش‌ها» (بهترین تجارب | Best Practices) و اصول اثبات شده‌ای است.
  • «دیباگ آسان‌تر»(Easier Debugging): به‌کارگیری دیزاین پترن‌ها، کدهای ساخت‌یافته‌تر و «منظم‌تر» (Organized) را به‌وجود خواهد آورد که تشخیص و همچنین رفع ساده‌تر مشکلات به هنگام «دیباگ» (اِشکال‌زدایی | Debugging) را به‌دنبال خواهد داشت.
  • «ثبات و سازگاری در طراحی» (Design Consistency): دیزاین پترن‌ها، رویکرد یکپارچه‌ای برای حل مسائل خاص فراهم می‌کنند که علاوه بر سازگاری بیشتر در سراسر اپلیکیشن، به اعضای جدید تیم در دریافت اطلاعاتِ به‌روز کمک می‌کند.

از دیگر سودمندی‌های به‌کارگیری دیزاین پترن‌ها می‌توانیم به مواردی اشاره کنیم که در ادامه بیان شده است.

  • الگوهای طراحی به‌صورت «از پیش تعریف شده‌» هستند و رویکردی استاندارد برای حل مسائل و مشکلات رایج – که به دفعات پیش می‌آیند – ارائه می‌دهند. بنابراین اگر به‌طور مناسب و به‌جا از دیزاین پترن‌ها استفاده کنیم، باعث صرفه‌جویی زمان در هنگام توسعه برنامه می‌شوند.
  • استفاده از الگوهای طراحی، «قابلیت استفاده مجدد» (Reusability) را افزایش می‌دهد که در نتیجه، تولید کد بهتری را به‌دنبال خواهد داشت که قابلیت نگهداری بالایی دارد. این مورد باعث کاهش «هزینه کل مالکیت» (Total Cost of Ownership | TCO) محصولِ نرم‌افزاری نیز می‌شود.

معایب استفاده از دیزاین پترن چیست؟

علیرغم نتایج مثبت دیزاین پترن‌های نرم‌افزاری و مزایای بسیاری که در اختیارمان قرار می‌دهند، برخی معایب را می‌توان برای آن‌ها بیان کرد که در ادامه به آن‌ها اشاره می‌کنیم.

  • «استفاده بی‌رویه یا نا‌به‌جا» (Overuse or Misuse): به‌کارگیری نامناسب دیزاین پترن‌ها یا استفاده غیر ضروری از این الگوها، می‌تواند باعث افزایش پیچیدگی کدها شود و تأثیر منفی روی «قابلیت نگهداری» (نگهداشت‌پذیری | Maintainability) آن داشته باشد.
  • «منحنی یادگیری» (Learning curve): درک و اجرایِ برخی از دیزاین پترن‌ها چالش برانگیز است و برای کسب مهارت و مسلط شدن روی آن، نیاز به صرف زمان و تلاش زیادی است.
  • «بهینه‌سازی زودرس» (Premature Optimization): متکی بودن بیش از اندازه به دیزاین پترن‌ها در اوایل فرایند توسعه، می‌تواند «بهینه‌سازی بیش از اندازه» (Over-Optimization) را به‌دنبال داشته باشد که در نتیجه، علاوه‌بر ایجاد «پایگاه کد» (کُد بِیس | Codebase) پیچیده، ممکن است الزامات مورد نظر را نیز برآورده نسازد.
  • «انعطاف پذیری محدود» (Limited Flexibility): برخی از دیزاین پترن‌ها می‌توانند منجر به محدودیت‌هایی در طراحی نرم‌افزار شوند , «انعطاف‌پذیری» را در مواقعی خاصی محدود کنند. توسعه‌دهندگان، باید به این سوال پاسخ دهند که آیا به‌کارگیری پترن مورد نظر، با‌ توجه‌به مزایا و همچنین اشکلات احتمالی که ممکن است در آن کاربرد خاص – مورد نظر – به‌دنبال داشته باشد، برایش به‌صرفه است یا خیر.

انواع دیزاین پترن چیست؟

بر اساس کتاب «GoF Design Patterns»، دیزاین پترن‌ها را می‌توان به ۳ دسته کلی تقسیم کرد که عناوین آن‌ها را در ادامه، فهرست کرده‌ایم.

  1. دیزاین پترن‌های «سازنده» (Creational): دیزاین پترن‌های این دسته با «ساختِ شی» (شی | Object) سروکار دارند.
  2. دیزاین پترن‌های «ساختاری» (Structural): دیزاین پترن‌‌های مرتبط با ساختار «کلاس» (Class) نظیر وراثت یا «ترکیب» (کامپوزیشن | Composition) در این دسته قرار می‌گیرند.
  3. دیزاین پترن‌های «رفتاری» (Behavioral): این نوع از دیزاین پترن‌ها، راهکاری برای تعامل بهتر میان «اشیا» (Objects)، نحوه ارائه «اتصال سُست» (Loose Coupling) و «انعطاف‌پذیری» برای توسعه آسان در آینده را فراهم می‌کنند.

دیزاین پترن‌های سازنده

دیزاین پترن‌های «سازنده» (مربوط به خلق کردن | Creational)، به مکانیزم و چگونگی ایجاد «اشیا» (Object) می‌پردازند و سعی دارند تا اشیا را با روشی متناسب با موقعیت، ایجاد کنند.

برای دسته «Creational» یا «سازنده»، ۵ دیزاین پترن وجود دارد که در ادامه، معرفی شده‌اند.

  1. Singleton: پترن سینگِلتون، مقداردهی اولیه کلاس را محدود می‌کند، با هدف اطمینان از اینکه تنها یک نمونه از کلاس می‌تواند ساخته شود.
  2. Factory: پترن فَکتوری، وظیفه نمونه‌سازی شی از کلاس آن را به کلاس فَکتوری منتقل می‌کند.
  3. Abstract Factory: امکان ایجاد فَکتوری برای کلاس‌های فکتوری را برایمان فراهم می‌کند.
  4. Builder: ساخت شی به‌صورت گام‌ به‌ گام و روشی برای گرفتن نمونه شی را فراهم می‌کند.
  5. Prototype: ساخت نمونه شی جدید از نمونه مشابه دیگر و تغییر آن با توجه به نیازهایمان را اماکن‌پذیر می‌کند.

این نوع از دیزاین پترن‌ها، همگی به «نمونه‌سازی کلاس» (Class Instantiation) یا «ایجاد شی» مربوط هستند. این پترن‌ها را می‌توان به پترن‌های «ایجاد کلاس» (Class-Creational) و پترن «ایجاد شی» (Object-Creational) تقسیم کرد.

  • الگوهای ایجاد کلاس، به طور مؤثر از «وراثت» (Inheritance) در فرایند نمونه‌سازی استفاده می‌کنند.
  • الگوهای ایجاد شی، به طور مؤثر از «تفویض» (Delegation | محول‌سازی) برای انجام کار استفاده می‌کنند.

کاربرد دیزاین پترن‌های سازنده چیست؟

در ادامه، مثال‌هایی را آورده‌ایم که با به‌کارگیری دیزاین پترن‌های این دسته قابل انجام است.

  1. فرض کنید برنامه‌نویسی می‌خواهد کلاس DBConnection

     ساده‌ای را برای اتصال به پایگاه داده مورد نظر بسازد و همچنین قصد دارد در چندین مکان از کدهای خود به پایگاه داده دسترسی پیدا کند، معمولاً در این مواقع، برنامه‌نویس، نمونه‌ای از کلاس DBConnection

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

    اتصال جداگانه‌ای به پایگاه داده خواهد داشت. برای مقابله با این مشکل، می‌بایست کلاس DBConnection

    را به‌عنوان کلاسی «Singleton» بسازیم، به منظور اینکه که تنها یک نمونه از DBConnection

    ایجاد و «اتصالی واحد» برقرار شود. همچنین با توجه به اینکه مدیریت اتصال پایگاه داده به‌وسیله یک نمونه انجام می‌شود، می‌توانیم مواردی مانند تعادل بار، اتصالات غیر ضروری و غیره را نیز کنترل کنیم.

  2. فرض کنید می‌خواهیم نمونه‌های متعددی از نوعی یکسان بسازیم و همچنین «اتصالی سُست» داشته باشیم، اینجا است که به سراغ دیزاین پترن «Factory» می‌رویم. کلاسی که دیزاین پترن «فکتوری» را پیاده‌سازی می‌کند به‌عنوان پُلی بین کلاس‌های متعدد عمل می‌کند. مثالی از به‌کارگیری چندین سرور پایگاه داده مانند «SQL Server» و «اوراکل» (Oracle) را در نظر بگیرید. اگر در حال توسعه اپلیکیشنی با استفاده از پایگاه داده «SQL Server» به‌عنوان «بَک اِند» (Back end) هستید، اما در آینده نیاز است تا پایگاه داده «اوراکل» را جایگرین آن کنید، اینجا است که به سراغ دیزاین پترن «کارخانه» می‌رویم و باید تمام کدهایمان را به‌نحوی تغییر دهیم که دیزاین پترن «کارخانه»، اتصالِ سست و «سادگی پیاده‌سازی» را حفظ کنند.

دیزاین پترن‌های ساختاری

دیزاین پترن‌های «ساختاری» (Structural)، به کامپوزیشن – یا ترکیب – اشیا پرداخته و به این ترتیب ساختارهای بزرگ‌تر را با استفاده از اشیا منفرد می‌سازند. پترن‌های ساختاری شامل ۷ مورد هستند که در ادامه، معرفی شده‌اند.

  1. Adapter: دیزاین پترن «اَداپتِر» یا «وفق‌دهنده»، رابطی بین ۲ موجودیت غیر مرتبط فراهم می‌کند، با هدف اینکه بتوانند با هم کار کنند و تعامل داشته باشند.
  2. Composite: کاربرد دیزاین پترن «کامپوزیت»، زمانی است که می‌خواهیم سلسله مراتب «بخشی از کل» را پیاده‌سازی کنیم. برای نمونه، نموداری را تصور کنید که از بخش‌های دیگری مانند دایره، مربع، مثلث و غیره تشکیل شده است.
  3. Proxy: دیزاین پترن «پروکسی»، «Placeholder» یا جایگزینی برای شی دیگر به منظور مدیریت دسترسی به آن فراهم می‌کند.
  4. Flyweight: به منظور «کَش کردن» و استفاده مجدد از نمونه‌های شی، هنگام کار با اشیا غیر قابل تغییر استفاده می‌شود. برای نمونه می‌توان به «String Pool» در زبان جاوا اشاره کرد.
  5. Facade: دیزاین پترن «فَساد»، رابط‌هایی پوششی – یا Wrapper – روی رابط‌های فعلی می‌سازد تا از این طریق به برنامه‌های کاربر – یا کلاینت – کمک کند.
  6. Bridge: دیزاین پترن «پُل»، برای جداسازی رابط‌ها – یا اینترفیس‌ها – از پیاده‌سازی و مخفی کردن جزئیات پیاده‌سازی از برنامه کاربر مورد استفاده قرار می‌گیرند.
  7. Decorator: دیزاین پترن «دِکُرِیتور» یا «آذین‌گر» برای اصلاح و تغییر عملکرد یک شی در زمان اجرا به‌کار می‌رود.

کاربرد دیزاین پترن‌های ساختاری چیست؟

زمانی‌که ۲ اینترفیس با هم سازگاری ندارند و بخواهیم به‌وسیله سازگار‌کننده‌ رابطه‌ای بین این ۲ ایجاد کنیم.از دیزاین پترنی به‌نام «Adapter» استفاده می‌کنیم. پترن آداپتور، اینترفیس یک کلاس را به کلاس یا اینترفیس دیگری – که مورد نظر کلاینت است تبدیل می‌کند – به بیان دیگر «Adapter» این امکان را برای کلاس‌ها فراهم می‌کند تا بتوانند با هم کار کنند – پیش از این به دلیل وجود ناسازگاری نمی‌توانستند – بنابراین در این نوع سناریوهای ناسازگار، می‌توانیم به سراغ الگوی آداپتور برویم.

دیزاین پترن‌های رفتاری

عناوین و توضیحات مربوط به ۱۱ مورد از دیزاین پترن‌های «رفتاری» (Behavioral) را در ادامه بیان کرده‌ایم. پترن‌های «رفتاری»، به ارتباط بین اشیا می‌پردازند و راهکارهایی برای تعاملی موجود بین اشیا و اینکه چگونه با هم کار می‌کنند را ارائه می‌دهد.

  1. Template Method: دیزاین پترن «تِمپلِیت مِتُد»، برای ایجاد «روش قالب» و محول نمودن برخی گام‌های پیاده‌سازی به «زیر کلاس‌ها» (Subclasses) به‌کار برده می‌شود.
  2. Mediator: دیزاین پترن «میانجی» یا «واسطه»، برای ارائه رسانه ارتباطی متمرکز بین اشیا گوناگونِ یک سیستم، مورد استفاده قرار می‌گیرد.
  3. Chain of Responsibility: دیزاین پترن «زنجیره مسئولیت»، برای دستیابی به «اتصال سُست» – با هدف کاهش وابستگی – در طراحی نرم‌افزار مورد استفاده قرار می‌گیرد. یعنی درخواست کاربر – یا کلاینت – به زنجیره‌ای از اشیا ارسال می‌شود تا آن‌ها را پردازش کند.
  4. Observer: استفاده از دیزاین پترن «مشاهده‌گر»، زمانی مفید است که می‌خواهیم از وضعیت یک شی، مطلع و همچنین هنگام رخداد هر تغییری، از آن با خبر شویم.
  5. Strategy: از دیزاین پترن «استراتژی» در مواقعی استفاده می‌کنیم که برای تَسک – یا کار – خاصی، الگوریتم‌های متعددی در اختیار داشته باشیم و کاربر – یا کلاینت – تعیین می‌کند که کدام پیاده‌سازی در زمان اجرا، مورد استفاده قرار گیرد.
  6. Command: دیزاین پترن «کامَند» یا «فرمان»، برای پیاده‌سازی اتصالِ سُست در یک مدل «درخواست-پاسخ» (Request-Response)، مورد استفاده قرار می‌گیرد.
  7. State: زمانی‌که یک شی رفتارش را بر اساس وضعیت داخلی‌اش تغییر می‌دهد از این دیزاین پترن استفاده می‌کنیم.
  8. Visitor: دیزاین پترن «ویزیتور»، زمانی به‌کار گرفته می‌شود که می‌خواهیم عملیاتی را روی مجموعه‌ای از اشیای هم نوع انجام دهیم.
  9. Interpreter: دیزاین پترن «مفسر»، نمایشی‌گرامری برای زبان، تعریف کرده و مفسری را برای کار با این گرامر عرضه می‌کند.
  10. Iterator: دیزاین پترن «پیمایشگر»، روشی استاندارد برای پیمایش میان گروهی از اشیا را فراهم می‌کند.
  11. Memento: کاربرد دیزاین پترن «مِمِنتو» زمانی است که می‌خواهیم وضعیت یک شی را ذخیره و نگه‌داری کنیم با این هدف که بعداٌ و در صورت لزوم، آن را بازیابی کنیم.

کاربرد دیزاین پترن‌های رفتاری چیست؟

به‌عنوان نمونه، پترن «Template» به‌عنوان یکی از پترن‌های رفتاری، چارچوب و ساختار الگوریتمی‌را در یک عملیات مشخص می‌کند و مواردی از این مراحل را به کلاس‌های فرزند یا همان «زیرکلاس‌ها» (Sub-Classes) موکول می‌کند. روش «Template» این امکان را برای زیر‌کلاس‌ها فراهم می‌کند تا بدون ایجاد تغییر در ساختار الگوریتم، مراحل مشخصی از آن را دوباره تعریف کنند. به ‌عنوان مثال، در پروژه خود می‌خواهیم که رفتار یک ماژول توانایی گسترش داشته باشد، به شکلی که با تغییر الزامات برنامه یا برآورده ساختن نیاز‌های برنامه‌های جدید، این ماژول بتواند به‌صورت متفاوت – و جدیدی – رفتار کند. با این وجود، کسی مجاز نیست تا سورس کد را تغییر دهد، یعنی می‌توانیم مواردی را به آن اضافه کنیم، اما اجازه تغییر ساختار را نداریم. در چنین سناریوهایی، برنامه‌نویس می‌تواند دیزاین پترن «قالب» را مورد استفاده قرار دهد.

سوالات متداول

در این قسمت، برخی از پرسش‌های رایج در مورد دیزاین پترن‌ها را به‌همراه پاسخ‌های متناظرشان بیان کرده‌ایم.

دیزاین پترن ها به چند دسته تقسیم می‌شوند؟

دیزاین پترن‌ها به طور کلی به ۳ دسته سازنده، ساختاری و رفتاری تقسیم می‌شوند.

نوع سازنده در دیزاین پترن چیست؟

دیزاین پترن سازنده یا Creational، راهکار‌هایی را برای نمونه‌سازی یک شی به بهترین شکل ممکن برای موقعیت‌های خاص فراهم می‌کند.

انواع دیزاین پترن سازنده چیست؟

از دیزاین پترن‌های سازنده می‌توان به الگوهای سینگلتون، کارخانه، کارخانه انتزاعی، بیلدر و پروتوتایپ اشاره کرد.

نوع ساختاری در دیزاین پترن چیست ؟

دیزاین پترن ساختاری یا Structural، راه‌های مختلفی را برای ایجاد ساختار کلاس‌ها فراهم می‌کنند. به‌عنوان مثال، برای اینکه از اشیا کوچک، شیئی بزرگ بسازند از «وراثت» (Inheritance) و «ترکیب» (Composition) کمک می‌گیرند.

انواع دیزاین پترن ساختاری چیست؟

از انواع دیزاین پترن‌های ساختاری می‌توان به الگوهای اَداپتِر، کامپوزیت، پروکسی، فِلای‌وِیت، فَساد، پُل و دِکوریتور اشاره کرد.

نوع رفتاری در دیزاین پترن چیست؟

پترن‌های «رفتاری» (Behavioral)، راهکاری را برای تعاملِ بهتر اشیا باهم، امکان گسترش آسان با وجود «اتصال سست» (Loose-Coupling) و انعطاف‌پذیری ارائه می‌دهند.

انواع دیزاین پترن رفتاری چیست؟

از دیزاین پترن‌های ساختاری می‌توان الگوهای میانجی، زنجیره مسئولیت‌ها، مشاهده‌گر، استراتژی، فرمان، وضعیت، مترجم، تکرارشونده و یادآور را نام برد.

لزوم یادگیری الگوهای طراحی چیست؟

به‌عنوان برنامه‌نویس، می‌توانیم از دیزاین پترن‌های نرم‌افزاری برای ایجاد ساختارهایی با قابلیت اطمینان بیشتر کمک بگیریم. دیزاین پترن‌ها در واقع، مهارت‌های مربوط به ساخت نرم‌افزار یا اپلیکیشن‌های هوشمند و تعاملی را با روش‌های ساده و آسان «حل مسئله» (Problem-Solving)، در اختیارمان قرار می‌دهند. دیزاین پترن‌ها همچنین، این امکان را برایمان فراهم می‌کنند تا برنامه‌های بسیار کاربرپسندی را بسازیم و آن‌ها را به‌آسانی برای تطبیق با آخرین نیازها تغییر دهیم. جذابیت دیزاین پترن‌ها از این بابت است که روش‌های ساختاری و پترن‌های کدنویسی انعطاف‌پذیر، کدهایی با قابلیت استفاده مجدد و غیره را فراهم می‌کنند.

چرا باید دیزاین پترن‌ها و کاربردهای آن آشنا شویم؟

یادگیری و همچنین به‌کار بردن دیزاین پترن‌ها مفید است. در ادامه، دلایلی را در این مورد بیان کرده‌ایم.

  • دیزاین پترن‌ها، ایده‌های بیشتر و بهتری را در مورد نحوه مدل‌سازی مسائل فنی خاص، عرضه می‌کنند.
  • امکان استفاده مجدد و به‌کارگیری ایده‌های طراحی که مؤثر بودن آن‌ها ثابت شده‌است، وجود دارد.
  • می‌توانیم جزئیات مناسب‌تری از کلاس‌هایمان به‌دست آوریم که حوزه خاصی را مدل‌سازی می‌کنند.

جمع‌بندی

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

مفهوم «الگوهای طراحی» یا «دیزاین پترن‌ها»، تأثیر قابل توجهی در مهندسی نرم‌افزار داشته است و برای برنامه‌نویسان با تجربه، مفهوم آشنایی محسوب می‌شود که از آن برای یافتن راهکارهایی در مسائل طراحی و توسعه نرم‌افزار کمک می‌گیرند. به‌کارگیری پترن‌ها و مواردی که در این مطلب بیان شد، به توسعه‌دهندگان تحمیل نمی‌شود – و اجباری در استفاده از آن‌ها وجود ندارد – بلکه هدف این بوده تا دستورالعمل‌هایی برای حل مشکلات رایج در طراحی، پیشنهاد شوند. هر کدام از این الگوها را می‌توان متناسب با نیازهای پروژه مورد نظر سازگار کرد. همچنین می‌توان پترن‌ها را ترکیب و به روش‌های مختلف به منظور ایجاد راهکارهای جدید، مورد استفاده قرار داد. البته لازم است به این نکته توجه داشته باشیم که نباید از این پترن‌ها به‌صورت کورکورانه و بدون دانش، استفاده شود، بلکه باید با در نظر گرفتن مسئله خاصی که نیاز به حل دارد، دقت و ملاحضات لازم را به خرج دهیم.