مقدمه‌ای بر الگوهای طراحی (Design patterns)

الگوهای طراحی (Design patterns) مدل‌هایی از کد هستند که مشکلات کلاسیک را حل می‌کنند. آنها راه‌حل‌هایی برای مشکلات طراحی نرم‌افزار هستند که می‌توان آنها را در کاربردهای واقعی یافت. یک الگوی طراحی کدی نیست که آماده استفاده در برنامه شما باشد، بلکه مدلی است که می‌توانید از آن برای حل یک مسئله استفاده کنید.
الگوهای طراحی مستقل از زبان برنامه‌نویسی هستند و بنابراین می‌توانند در هر زبانی که از شی‌ءگرایی پشتیبانی می‌کند اعمال شوند.

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

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

گاهی اوقات نیازی به استفاده از یک الگوی طراحی نیست و این نکته مهمی است که باید به خاطر بسپاریم؛ باید از آن فقط در مواقع ضروری استفاده کنیم. هر الگوی طراحی برای موقعیت خاصی قابل استفاده است و این یکی از دلایلی است که چرا آشنایی با آنها اهمیت دارد؛ زیرا ممکن است شما با مشکلی روبه‌رو شوید که یک مشکل شناخته‌شده در دنیای توسعه نرم‌افزار باشد و راه‌حل خوبی برای حل آن از طریق یک الگوی طراحی وجود داشته باشد. به این ترتیب، نیازی به “اختراع دوباره چرخ” نخواهید داشت؛ می‌توانید از چیزی که قبلاً وجود دارد و به‌خوبی کار می‌کند استفاده کنید. بنابراین بهترین راه برای دانستن اینکه چه زمانی باید از آن استفاده کرد یا نکرد، این است که الگوها را یاد بگیرید و درک کنید که هر الگوی طراحی کدام مشکل را حل می‌کند.

گروه چهار نفره (GoF)

در سال 1995، چهار توسعه‌دهنده، اریک گاما، ریچارد هلم، رالف جانسون و جان ویسیدیس، که به عنوان “گروه چهار نفره” (GoF) شناخته می‌شوند، کتاب “Design Patterns: Elements of Reusable Object-Oriented Software” را منتشر کردند و مفهوم الگوها را معرفی کردند و 23 الگوی طراحی را معرفی نمودند. این الگوهای گروه چهار نفره به‌طور کلی به عنوان پایه‌ای برای تمام الگوهای دیگر در نظر گرفته می‌شوند و به سه دسته تقسیم می‌شوند:

  1. الگوهای طراحی ایجادی (Creational patterns) – مرتبط با فرآیند ایجاد (ساخت) اشیاء.
  2. الگوهای طراحی ساختاری (Structural patterns) – مرتبط با ترکیب کلاس‌ها و اشیا.
  3. الگوهای طراحی رفتاری (Behavioural patterns) – نشان‌دهنده شیوه‌های تعامل کلاس‌ها یا اشیا و توزیع مسئولیت‌ها.

عناصر یک الگوی طراحی

کتاب “Design Patterns” می‌گوید که یک الگو دارای چهار عنصر اساسی است:

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

در اینجا توضیح مختصری از هر یک از 23 الگوی طراحی آورده شده است. این تعاریف نیز از کتاب “Design Patterns” گروه چهار نفره آمده است:

الگوهای طراحی ایجادی

  • کارخانه انتزاعی (Abstract factory) – یک واسط برای ایجاد خانواده‌های اشیای مرتبط یا وابسته ارائه می‌دهد بدون آنکه کلاس‌های خاص آنها را مشخص کند.
  • سازنده (Builder) – فرآیند ساخت یک شیء پیچیده را از نمایش آن جدا می‌کند به‌گونه‌ای که همان فرآیند ساخت بتواند نمایش‌های مختلفی ایجاد کند.
  • متد کارخانه (Factory method) – یک واسط برای ایجاد یک شیء تعریف می‌کند، اما به زیرکلاس‌ها اجازه می‌دهد تصمیم بگیرند که کدام کلاس را نمونه‌سازی کنند. متد کارخانه به یک کلاس اجازه می‌دهد نمونه‌سازی را به زیرکلاس‌ها واگذار کند.
  • نمونه اولیه (Prototype) – انواع اشیایی که باید ایجاد شوند را با استفاده از یک نمونه اولیه مشخص می‌کند و با کپی‌کردن این نمونه اولیه، اشیاء جدید ایجاد می‌کند.
  • سینگلتون (Singleton) – اطمینان حاصل می‌کند که یک کلاس فقط یک نمونه دارد و نقطه دسترسی جهانی به آن را فراهم می‌کند.

الگوهای طراحی ساختاری

  • مُبَدّل (Adapter) – رابط یک کلاس را به رابطی دیگر تبدیل می‌کند که مشتریان انتظار دارند. مبدل به کلاس‌ها اجازه می‌دهد که با وجود رابط‌های ناسازگار، با یکدیگر کار کنند.
  • پل (Bridge) – یک انتزاع را از پیاده‌سازی آن جدا می‌کند به‌گونه‌ای که هر دو بتوانند به‌طور مستقل تغییر کنند.
  • ترکیب (Composition) – اشیا را به ساختارهای درختی ترکیب می‌کند تا سلسله‌مراتب جز-کل را نمایش دهد. ترکیب به مشتریان اجازه می‌دهد تا با اشیاء فردی و ترکیبات اشیاء به‌طور یکنواخت رفتار کنند.
  • دکوراتور (Decorator) – مسئولیت‌های اضافی را به‌صورت پویا به یک شیء پیوست می‌کند. دکوراتورها جایگزین انعطاف‌پذیری برای زیرکلاس‌سازی برای گسترش قابلیت‌ها ارائه می‌دهند.
  • نما (Facade) – یک واسط یکپارچه برای مجموعه‌ای از واسط‌ها در یک زیرسیستم ارائه می‌دهد. نما یک واسط سطح بالاتر تعریف می‌کند که استفاده از زیرسیستم را آسان‌تر می‌سازد.
  • پَروَزن (Flyweight) – از به اشتراک‌گذاری برای پشتیبانی از تعداد زیادی از اشیاء با دانه‌بندی ریز به‌طور کارآمد استفاده می‌کند.
  • نایب (Proxy) – یک جانشین یا نگه‌دارنده برای یک شیء دیگر فراهم می‌کند تا دسترسی به آن را کنترل کند.

الگوهای طراحی رفتاری

  • زنجیره مسئولیت (Chain of responsibility) – از متصل‌کردن فرستنده یک درخواست به گیرنده خود جلوگیری می‌کند و بیش از یک شیء را برای مدیریت درخواست شانس می‌دهد. شی‌های دریافت‌کننده را زنجیره می‌کند و درخواست را در امتداد زنجیره عبور می‌دهد تا یک شیء آن را مدیریت کند.
  • دستور (Command) – یک درخواست را به‌عنوان یک شیء کپسوله می‌کند و به این ترتیب به مشتریان امکان می‌دهد با درخواست‌های مختلف، صف یا درخواست‌های ثبت شده و عملیات قابل لغو، پارامترگذاری شوند.
  • مترجم (Interpreter) – با ارائه یک زبان، یک نمایش برای دستور زبان آن همراه با یک مترجم که از این نمایش برای تفسیر جملات زبان استفاده می‌کند، تعریف می‌کند.
  • تکرارگر (Iterator) – راهی برای دسترسی به عناصر یک شیء ترکیبی به‌طور متوالی بدون آشکارسازی نمایش زیرین آن فراهم می‌کند.
  • میانجی (Mediator) – یک شیء تعریف می‌کند که نحوه تعامل یک مجموعه از اشیا را کپسوله می‌کند. میانجی موجب کاهش اتصال بین اشیا می‌شود و به آنها اجازه می‌دهد تا تعامل خود را به‌طور مستقل تغییر دهند.
  • یادبود (Memento) – بدون نقض کپسوله‌سازی، وضعیت داخلی یک شیء را ضبط و خارجی‌سازی می‌کند تا بتوان شیء را در آینده به این حالت بازگرداند.
  • ناظر (Observer) – یک وابستگی یک به چند بین اشیاء تعریف می‌کند به‌طوری‌که وقتی یک شیء تغییر وضعیت می‌دهد، تمام وابستگان آن به‌طور خودکار مطلع و به‌روزرسانی می‌شوند.
  • حالت (State) – به یک شیء اجازه می‌دهد که وقتی وضعیت داخلی آن تغییر می‌کند، رفتار خود را تغییر دهد. شیء به نظر می‌رسد که کلاس خود را تغییر می‌دهد.
  • استراتژی (Strategy) – خانواده‌ای از الگوریتم‌ها را تعریف و هر کدام را کپسوله کرده و قابل تعویض می‌کند. استراتژی به الگوریتم اجازه می‌دهد به‌طور مستقل از مشتریانی که از آن استفاده می‌کنند تغییر کند.
  • متد قالب (Template method) – اسکلت یک الگوریتم را در یک عملیات تعریف می‌کند و برخی از مراحل را به زیرکلاس‌ها واگذار می‌کند. روش متد قالب به زیرکلاس‌ها اجازه می‌دهد برخی از مراحل یک الگوریتم را بدون تغییر ساختار الگوریتم بازتعریف کنند.
  • بازدیدکننده (Visitor) – یک عملیات را تعریف می‌کند که باید روی عناصر یک ساختار شیء اجرا شود. بازدید کننده به شما امکان می‌دهد یک عملیات جدید بدون تغییر کلاس‌های عناصر که بر روی آنها اعمال می‌شود تعریف کنید.

نتیجه‌گیری

الگوهای طراحی برای کمک به ما، توسعه‌دهندگان، وجود دارند. البته یک منحنی یادگیری اولیه برای یادگیری نحوه کار با آنها وجود دارد، اما هنگامی که آنها را یاد گرفتید، می‌توانند کار شما را آسان‌تر کنند.

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