الگوی طراحی نرم‌افزار

از ویکی‌پدیا، دانشنامهٔ آزاد

در مهندسی نرم‌افزار، الگوی طراحی[۱] (به انگلیسی: design pattern) یک راه‌حل عمومی قابل تکرار برای مشکلات متداول در زمینه طراحی نرم‌افزار است. الگوی طراحی، یک طراحی تمام‌شده نیست که به صورت مستقیم بتواند تبدیل به کد منبع یا ماشین شود؛ بلکه، یک توضیح یا قالب برای حل یک مسئله در شرایط مختلف است. الگوها در واقع بهترین روش ممکن هستند که یک برنامه‌نویس می‌تواند در هنگام طراحی یک برنامه برای حل مشکلاتش از آن‌ها استفاده کند. الگوهای طراحی شیءگرا نوعاً نشان‌دهندهٔ روابط و تعامل‌ها بین کلاس‌ها و شیء‌ها هستند، بدون این‌که کلاس‌ها یا اشیا نهایی برنامه را مشخص کند. الگوهایی که در خود وضعیت‌های تغییرپذیر دارند، شاید مناسب زبان‌های برنامه‌نویسی تابعی نباشند. همچنین، در بعضی از زبان‌ها که برای حل یک مسئله راه‌حل‌های آمادهٔ از پیش تعریف‌شده وجود دارد، استفاده از بعضی الگوها برای حل مسئلهٔ مشابه می‌تواند لازم نباشد. به همین ترتیب، الگوهای طراحی شیءگرا ممکن است برای زبان‌های غیر شیءگرا مناسب نباشند.[۲]

آشنایی با مفاهیم[ویرایش]

در الگوی طراحی از اشیاء ویژه‌ای به نام آداپتور (واسطه) استفاده می‌شود. این آداپتورها به اشیاء مورد نیاز در پروژه مرتبط می‌شوند. نوشتن برنامه تا حد زیادی از طریق این واسطه‌ها انجام می‌شود. الگوهای طراحی را بر اساس دو معیار طبقه‌بندی می‌کنیم.
۱-اولین معیار، که مقصود نامیده شده، منعکس‌کننده آنچه یک الگو انجام می‌دهداست. یک الگو ممکن است هدف ایجادی، ساختاری یا رفتاری داشته باشد.
الگوهای ایجادی پروسه ایجاد اشیاء را مورد توجه قرار می‌دهند.
الگوهای ساختاری با ترکیب کلاس‌ها و اشیاء سروکار دارند.
الگوهای رفتاری طرقی که اشیاء با همدیگر فعل و انفعال انجام داده و وظایف را توزیع می‌کنند مشخص می‌سازند.
۲- معیار دوم، که محدوده نامیده شده، مشخص‌کننده اینکه الگو بر روی کلاس‌ها یا اشیاء اعمال می‌گردد. است. الگوهای در محدوده کلاس‌ها با ارتباطات بین کلاس‌ها و زیر کلاس‌های آن‌ها سر و کار دارند. این‌گونه ارتباطات از طریق وراثت برقرار می‌گردد، که بنابراین در زمان کامپایل ثابت می‌شوند. الگوهای در محدوده اشیاء با ارتباطات بین اشیاء سرو کار داشته که می‌تواند در زمان اجرا تغییر کرده و در نتیجه پویا هستند. تقریباً تمام الگوها از وراثت استفاده می‌کنند؛ بنابراین الگوهایی که با برچسب «در محدوده کلاس» معین شده‌اند آن‌هایی هستند که تنها بر روی ارتباط بین کلاس‌ها تأکید دارند. توجه کنید که بیشتر الگوها در محدوده اشیاء عمل می‌کنند.
الگوهای ایجادی که در محدوده کلاس‌ها هستند قسمتی از ایجاد اشیاء را به زیر کلاس‌ها محول می‌کنند، درحالی‌که الگوهای ایجادی در محدوده اشیاء چنین عملی را به شیء دیگری محول می‌نمایند.
الگوهای ساختاری کلاسی از وراثت برای ترکیب کلاس‌ها استفاده کرده در عوض الگوهای ساختاری در محدوده اشیاء روش‌هایی برای آمیختن اشیاء را شرح می‌دهند.
الگوهای رفتاری کلاسی از وراثت برای تشریح الگوریتم‌ها و کنترل جریان اجرای برنامه‌ها استفاده می‌کنند در صورتی‌که الگوهای رفتاری شیئی چگونگی همکاری گروهی از اشیاء برای انجام یک وظیفه که یک شیء به تنهایی نمی‌تواند به انجام رساند را شرح می‌دهند.

تاریخچه[ویرایش]

بحث Design Pattern برای اولین بار در دنیای نرم‌افزار توسط GoF صورت گرفت. یک گروه چهار نفره شامل: Erich Gamma ,Richard Helm ,Ralph Johnson و John Vlissides ملقب به Gang of Four یا GoF هستند.

این گروه در ۲۱ اکتبر سال ۱۹۹۴ کتابی را تحت عنوان Design Patterns: Elements of Reusable Object-Oriented Software منتشر کردند. (این کتاب تا تاریخ آوریل ۲۰۰۷، سی و شش بار تجدید چاپ شده‌است)

آن‌ها در این کتاب ۲۳ الگوی طراحی کلاسیک را با زبان‌های شی گرا مطرح در آن زمان (++C و Smalltalk) برای اولین بار مورد بحث قرار دادند.

کاربرد[ویرایش]

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

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

طبق تعریف، برای استفاده از الگوها در هر برنامه‌ای که از آن‌ها استفاده می‌کند، باید از نو برنامه‌نویسی کرد. از آن‌جایی که بعضی از نویسندگان این نکته را مخالف با استفاده مجدد از کد (به انگلیسی: Code reuse) آن‌گونه که توسط مهندسی نرم‌افزار بر پایه مؤلفه (به انگلیسی: Component-based software engineering) فراهم می‌شود، می‌بینند، پژوهش‌گران تلاش کرده‌اند تا الگوها را به پیکرپارها تبدیل کنند. میر و آرنوت توانستند دو سوم الگوهایی را که رویشان کار می‌کردند، به صورت کامل یا جزئی به پیکرپار تبدیل کنند.[۴]

تکنیک‌های طراحی نرم‌افزار را به سختی می‌توان در گسترهٔ وسیع‌تری از مسائل به کار برد.[نیازمند منبع] الگوهای طراحی راه‌حل‌هایی کلی را در قالبی بیان می‌کنند که وابسته به مسئلهٔ مخصوصی نیست.

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

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

دسته‌بندی کلاسیک الگوها[ویرایش]

این ۲۳ الگو طبق دسته‌بندی فرض شده توسط آن‌ها (که هنوز هم رعایت می‌شود) در ۳ گروه زیر جای گرفتند:

الگوهای ایجادی[ویرایش]

نام توضیح در الگوهای طراحی در Code Complete[۵] سایر
Abstract factory رابطی برای ساخت فامیلی‌هایی از اشیاء مرتبط یا وابسته به هم بدون مشخص کردن کلاس‌های واقعی آن‌ها تدارک می‌بیند. آری آری
Builder فرایند ساخت یک شیء را از نمایش آن جدا کرده تا بتوان همان فرایند ساخت را برای ایجاد نمایش‌های مختلف بکار برد. آری نه
Factory method یک رابط برای ساخت اشیاء تعریف کرده و در عین حال اجازه می‌دهد تا زیر کلاس‌ها در مورد اینکه چه شیء را نمونه‌سازی کنند تصمیم بگیرند. در واقع این الگو اجازه می‌دهد تا نمونه‌سازی را به زیر کلاس‌ها محول نمود. آری آری
Lazy Initialization شیوهٔ تأخیر انداختن برای ساخت یک شیء، محاسبه یک مقدار یا پردازش‌های سنگین دیگر تا زمانِ اولین نیاز به آن‌ها. این الگو در فهرست GoF با نام «پروکسی مجازی» نیز شناخته می‌شود. یک استراتژی پیاده‌سازی برای الگوی Proxy به حساب می‌آید. آری نه PoEAA[۶]
Multiton این اطمینان را حاصل می‌کند که یک کلاس فقط نمونه‌های (instances) با نام دارد و یک نقطه سراسری (global) برای دسترسی به آن فراهم می‌کند. نه نه
Object pool با بازیابی اشیائی که دیگر مورد استفاده قرار نمی‌گیرند از اشغال و آزادسازی‌های سنگین منابع دوری می‌کند. نه نه
Prototype با استفاده از یک شیء به عنوان نمونه نوع اشیاء جدیدی که بایستی ساخته شوند را مشخص کرده و آن اشیاء را با ساختن کپی‌های جدید از این نمونه ایجاد می‌نماید. آری نه
Resource Acquisition Is Initialization این اطمینان را حاصل می‌کند که منابع به‌طور مناسب با تعیین طول عمر برای اشیاء آزادسازی می‌شوند. نه نه
Singleton این اطمینان را حاصل می‌کند که یک کلاس دارای تنها یک نمونه بوده و دسترسی به آن نمونه را تدارک می‌بیند.
آری آری
Object library کپسوله کردن مدیریت اشیاء شامل factory interface و لیست‌های مُرده و زنده نه نه

الگوهای ساختاری[ویرایش]

  • (Adapter) رابط یک کلاس را به رابط دیگری که مورد انتظار یک مشتری است تبدیل می‌کند. این الگو امکان همکاری بین اشیائی که قبلاً بخاطر داشتن رابط‌های ناسازگار نمی‌توانستند با هم کار کنند را فراهم می‌سازد.
  • (Bridge) یک مفهوم مجرد را از پیاده‌سازی اش مجزا کرده تا هردو بتوانند به‌طور مستقل تغییر کنند.
  • (کامپوزیت) اشیاء را به صورت ساختار درختی برای ایجاد ساختار سلسله مراتبی بفرم part-whole ترکیب می‌نماید. این الگو اجازه می‌دهد تا مشتری‌ها اشیاء منفرد و مرکب را به صورت یکسانی پردازش کنند.
  • (Decorator) در زمان اجرا وظایف جدیدی به یک شیء اضافه می‌کند. این الگو بدیلی قابل انعطاف برای گسترش عملکرد یک کلاس به وسیلهٔ زیر کلاس ساختن از آن را فراهم می‌کند.
  • (Facade) یک رابط منفرد برای مجموعه‌ای از رابط‌ها در یک زیر سیستم تدارک می‌بیند. در واقع یک facade رابط سطح بالاتری برای یک زیر سیستم تعریف کرده و باعث می‌شود تا زیر سیستم را به صورت ساده‌تری مورد استفاده قرار داد.
  • (Flyweight) از اشتراک منابع برای فراهم نمودن تعداد زیادی از اشیاء سبک به صورت کارا استفاده می‌کند.
  • (Proxy) یک جانشین یا جایگاه برای کنترل دسترسی به یک شیء ایجاد می‌کند.

الگوهای رفتاری[ویرایش]

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

انتقادها[ویرایش]

مفهوم الگوهای طراحی به روش‌های مختلفی مورد نقد قرار گرفته‌است.

الگوهای طراحی ممکن است تنها حاکی از کمبود برخی قابلیت‌ها و ویژگی‌ها در یک زبان برنامه‌نویسی (مانند جاوا یا سی++) باشد. پیتر نورویگ نشان داد که ۱۶ تا از ۲۳ الگوی طراحی در کتاب الگوهای طراحی (که عمدتاً روی زبان سی‌پلاس‌پلاس متمرکز شده‌است) از طریق پشتیبانی مستقیم در زبان‌های لیسپ یا دیلان ساده‌سازی یا زدوده شده‌است. اظهارات مشابهی نیز توسط هانمان و کیکزالس که شماری از ۲۳ الگوی طراحی را به کمک یک زبان برنامه‌نویسی جنبه‌گرا (AspectJ) پیاده‌سازی کرده بودند، انجام شد. این دو نشان دادند که وابستگی‌های سطح کد در پیاده‌سازی ۱۷ تا از ۲۳ الگوی طراحی از بین رفت و برنامه‌نویسی جنبه‌گرا توانست پیاده‌سازی الگوهای طراحی را ساده‌سازی کند.[۷] همچنین، مقالهٔ پاول گراهام را با عنوان «انتقام نردها» ببینید.[۸]

مهم‌تر آن که، استفادهٔ نامناسب از الگوها می‌تواند باعث افزایش پیچیدگی غیرضروری گردد.[۹]

منابع[ویرایش]

  1. «الگوی طراحی» [رایانه و فنّاوری اطلاعات] هم‌ارزِ «design pattern»؛ منبع: گروه واژه‌گزینی. جواد میرشکاری، ویراستار. دفتر پنجم. فرهنگ واژه‌های مصوب فرهنگستان. تهران: انتشارات فرهنگستان زبان و ادب فارسی. شابک ۹۷۸-۹۶۴-۷۵۳۱-۷۶-۴ (ذیل سرواژهٔ الگوی طراحی)
  2. «الگوهای طراحی چیست؟». http://pikneek.com/programming/الگوهای-طراحی-چیست؟/. بایگانی‌شده از اصلی در ۲ دسامبر ۲۰۱۷. دریافت‌شده در ۱۸ دسامبر ۲۰۱۷. پیوند خارجی در |وبگاه= وجود دارد (کمک)
  3. Bishop, Judith. "C# 3.0 Design Patterns: Use the Power of C# 3.0 to Solve Real-World Problems". C# Books from O'Reilly Media. Retrieved 2012-05-15. If you want to speed up the development of your .NET applications, you're ready for C# design patterns -- elegant, accepted and proven ways to tackle common programming problems.
  4. Meyer, Bertrand; Arnout, Karine (July 2006). "Componentization: The Visitor Example" (PDF). IEEE Computer. IEEE. 39 (7): 23–30. doi:10.1109/MC.2006.227.
  5. مک‌کانل, استیو (June 2004). "طراحی در ساخت". Code Complete (دوم ed.). انتشارات مایکروسافت. p. 104. ISBN 978-0-7356-1967-8. جدول 5.1 الگوهای طراحی محبوب
  6. Fowler, Martin (2002). Patterns of Enterprise Application Architecture. Addison-Wesley. ISBN 978-0-321-12742-6.
  7. Hannemann, Jan (2002). Design pattern implementation in Java and AspectJ.
  8. Graham, Paul (2002). Revenge of the Nerds. Retrieved 2012-08-11.
  9. McConnell, Steve (2004). Code Complete: A Practical Handbook of Software Construction, 2nd Edition. p. 105.

پیوند به بیرون[ویرایش]