شما اینجا هستید: خانه / مقالات آموزشی / الگوی طراحی Decorator

الگوی طراحی Decorator

Decorator یکی از الگوهای طراحی ساختاری (Structural Design Pattern) مطرح شده در کتاب معروف Design Pattern به تالیف GoF می باشد. در این مقاله به بررسی این الگو و کاربردهای آن می پردازیم.

 

  • هدف الگوی Decorator

هدف از پیاده سازی الگوی Decorator اضافه کردن یک وضعیت و یا یک رفتار (Behavior) به یک کلاس بدون تغییر دادن آن می باشد. این عمل می تواند کاملا به صورت داینامیک انجام شود. این دو مشخصه (تغییر نکردن کلاس فعلی و داینامیک بودن)، Decorator را تبدیل به یکی از پرکاربردترین الگوهای طراحی شیء گرا کرده است.

  • طرح مساله و مثال ساده

با یک مثال بسیار ساده به سراغ مشکل و سپس راه حل آن می رویم. کلاس های زیر را در نظر بگیرید :

یک اینترفیس به نام IComponent که توسط کلاس Component پیاده سازی شده است و متن ساده ای را برمی گرداند. متن برگردانده شده نیز بر روی صفحه چاپ می شود :

 اکنون فرض کنید نیاز دارید تا متن ساده را با حروف بزرگ (Uppercase) به کلاس استفاده کننده (در این مثال متد Main) برگردانید. از آنجا که (فرضا) کلاس Component در قست های دیگری از برنامه نیز استفاده شده است، تغییر آن برای شما مشکل بوده و یا مقدور نیست. اما چگونه می توانید رفتار جدید را بدون تغییر کلاس فعلی به آن اضافه کنید؟ یکی از راه حل هایی که شاید به ذهنتان رسیده، ارث بری از کلاس Component و Override کردن متد GetInfo باشد. اما ارث بری راه حلی تنها محدود به کلاس Component خواهد شد. برای مثال در صورتی که پیاده سازی دیگری از کلاس IComponent انجام شود، باز با مشکل فوق مواجه خواهیم شد. همچنین ارث بری در زمان اجرا (Runtime) قابل تغییر نبوده و محدود می باشد. از آن سو در صورتی که کلاس Component به صورت Sealed تعریف شده باشد، امکان ارث بری وجود ندارد.

  • راه حل Decorator 

decorator-pattern

 

نکته ی اصلی و کلیدی در پیاده سازی الگوی Decorator ارث بری از Interface اصلی و همچنین داشتن یک نمونه از آن در کلاس Decorator به صورت همزمان می باشد. به کد زیر دقت کنید :

 کلاسی با نام ComponentUppercaseDecorator تعریف شده است که هم IComponent را پیاده سازی کرده و هم شامل یک نمونه از آن می شود. سپس در پیاده سازی متد GetInfo از آن نمونه برای گرفتن متن استفاده کرده، و پس از Uppercase کردن آن، مقدار برگردانده می شود. همانطور که ملاحظه میکنید کلاس Component کوچکترین تغییری نمیکند. حال در کلاس Main از کلاس نوشته شده استفاده میکنیم :

حال با اجرای برنامه مشاهده خواهید کرد که متن به صورت Uppercase بر روی کنسول چاپ خواهد شد.

  • نکات مهم در پیاده سازی Decorator
    • کلاس اصلی (در مثال بالا Component) هیچ تغییری نمی کند و از وجود کلاس Decorator بی اطلاع است.
    • Decorator های مختلف از یکدیگر مستقل بوده و به همدیگر وابستگی ندارند.
    • توصیه می شود کلاس Decorator به Interface وابسته باشد و نه به کلاس پیاده سازی شده. (مانند این مثال که Decorator به IComponent وابستگی دارد و نه به Component)

 

  • مثال های کاربردی از الگوی Decorator

یادگیری Design Pattern ها نیازمند مطالعه و بررسی مثال های زیاد است. جهت یادگیری بهتر این الگو، پیشنهاد می شود منابع زیر را مطالعه کنید :

  1. کتاب C# Design Patterns – صفحه ۱۶ مثال Photo Decorator
  2. کتاب Professional ASP.NET Design Patterns – صفحه ی ۱۰۰ مثال ProductDecorator
  3. کتاب Head First Design Patterns – صفحه ی ۱۰۰ بخش Real World Decorators: Java IO (در این بخش به بررسی پکیج java.io پرداخته شده که در آن از الگوی Decorator جهت ساخت کلاس های مختلف  Stream استفاده شده است. همچنین در ادامه به پیاده سازی یک Stream جدید می پردازد. مطالعه ی این بخش برای یادگیری کاربردی این الگو به شدت توصیه می شود. همچنین می توانید به مطالعه ی ساختار System.IO.Stream در .NET Framework بپردازید زیرا در این Namespace نیز از الگوی Decorator بسیار استفاده شده است.)

درباره هادی احمدی

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

4 نظر

  1. باسلام
    من میخوام بدونم که از هرکدوم از الگوهای لایه دسترسی به داده که در ادامه ذکر شده چه موقع استفاده میشه-یعنی راهی برای تشخیص الگویی که میخوام در برنامه استفاده کنم لازم دارم-هرالگو برای چه شرایطی مناسب هست.متشکرم

    -unit of work

    -marker pattern unit of work

    -lazy loading , proxy

    -Identity map

    -query object

    -repository,generic repository

    • هادی احمدی

      سلام

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

      منابع بسیار زیادی در مورد هر یک از الگوهای فوق وجود دارد، می تونید سرچ بفرمایید.

  2. عالی بود . سپاسگزارم از زحماتتون

نظر بدهید

آدرس ایمیلتان منتشر نمیشودگزینه های الزامی ستاره دار شده اند *

*

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

رفتن به بالا