الگوی طراحی نرمافزار
در مهندسی نرمافزار، الگوی طراحی (به انگلیسی: 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) برای اولین بار مورد بحث قرار دادند.
کاربرد
الگوهای طراحی میتوانند سرعت فرایند توسعهٔ نرمافزار را با فراهم آوردن الگوهای توسعهٔ اثباتشده و مورد آزمون قرار گرفته افزایش دهند. طراحی نتیجهبخش نرمافزار نیازمند در نظر گرفتن پیامدهایی است که ممکن است هنوز در پیادهسازی قابل رؤیت نباشند، اما بعدها خود را نشان خواهند داد. استفاده از الگوهای طراحی کمک میکند تا از بروز خطاهای کوچک که ممکن است مشکلات بزرگی را ایجاد کنند، جلوگیری شود و علاوه بر آن، خوانایی کد را برای کدنویسان و معمارانی که با الگوها آشنا هستند، افزایش میدهد.
برای دستیافتن به انعطافپذیری در نرمافزار، الگوهای طراحی اغلب اعمال را به صورت غیرمستقیم انجام میدهند. این کار در شرایطی ممکن است طراحی حاصل را پیچیده کند و باعث افت کارایی برنامه شود.
طبق تعریف، برای استفاده از الگوها در هر برنامهای که از آنها استفاده میکند، باید از نو برنامهنویسی کرد. از آنجایی که بعضی از نویسندگان این نکته را مخالف با en:Code reuse آنگونه که توسط مهندسی نرمافزار بر پایه پیکرپار فراهم میشود، میبینند، پژوهشگران تلاش کردهاند تا الگوها را به پیکرپارها تبدیل کنند. میر و آرنوت توانستند دو سوم الگوهایی را که رویشان کار میکردند، به صورت کامل یا جزئی به پیکرپار تبدیل کنند.
تکنیکهای طراحی نرمافزار را به سختی میتوان در گسترهٔ وسیعتری از مسائل به کار برد. الگوهای طراحی راهحلهایی کلی را در قالبی بیان میکنند که وابسته به مسئلهٔ مخصوصی نیست.
گاهی اوقات برنامهنویسان هنگام طراحی یا پیادهسازی برنامههای خود، با کلاسهایی روبرو میشوند که اصطلاحاً کلاسهای کلاسیک نیستند. این گونه کلاسها مشکلاتی را ایجاد میکنند که با کمک الگوها میتوان مشکلات را تا حجم قابل قبولی حل کرد.
در واقع طراحی چنین کلاسهایی، به مرور زمان، گریبانگیر هر برنامهنویسی شدهاست و برنامه نویسان خبره با توجه به تجربیات شخصی خود و دیگران، تصمیم به ایجاد الگوهایی کردهاند که راه حل این گونه مشکلات خواهد بود. در حال حاضر شاید در حدود صدها الگو در این رابطه وجود داشته باشد که تنها تعداد اندکی از آنها استاندارد شده و مورد استفاده طراحان و برنامهنویسان قرار میگیرد.
دستهبندی کلاسیک الگوها
این ۲۳ الگو طبق دستهبندی فرض شده توسط آنها (که هنوز هم رعایت میشود) در ۳ گروه زیر جای گرفتند :
الگوهای ایجادی
نام | توضیح | در الگوهای طراحی | در 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) پیادهسازی کرده بودند، انجام شد. این دو نشان دادند که وابستگیهای سطح کد در پیادهسازی ۱۷ تا از ۲۳ الگوی طراحی از بین رفت و برنامهنویسی جنبهگرا توانست پیادهسازی الگوهای طراحی را سادهسازی کند. همچنین، مقالهٔ پاول گراهام را با عنوان «انتقام نردها» ببینید.
مهمتر آن که، استفادهٔ نامناسب از الگوها میتواند باعث افزایش پیچیدگی غیرضروری گردد.
منابع
- ↑ «الگوهای طراحی چیست؟». http://pikneek.com/programming/الگوهای-طراحی-چیست؟/. بایگانیشده از اصلی در ۲ دسامبر ۲۰۱۷. دریافتشده در ۱۸ دسامبر ۲۰۱۷.
- ↑ 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.
- ↑ Meyer, Bertrand; Arnout, Karine (July 2006). "Componentization: The Visitor Example" (PDF). IEEE Computer. IEEE. 39 (7): 23–30. doi:10.1109/MC.2006.227.
- ↑ مککانل, استیو (June 2004). "طراحی در ساخت". Code Complete (دوم ed.). انتشارات مایکروسافت. p. 104. ISBN 978-0-7356-1967-8.
جدول 5.1 الگوهای طراحی محبوب
- ↑ Fowler, Martin (2002). Patterns of Enterprise Application Architecture. Addison-Wesley. ISBN 978-0-321-12742-6.
- ↑ Hannemann, Jan (2002). Design pattern implementation in Java and AspectJ.
- ↑ Graham, Paul (2002). Revenge of the Nerds. Retrieved 2012-08-11.
- ↑ McConnell, Steve (2004). Code Complete: A Practical Handbook of Software Construction, 2nd Edition. p. 105.
- Wikipedia contributors, "Design Patterns," Wikipedia, The Free Encyclopedia, http://en.wikipedia.org/w/index.php?title=Design_Patterns&oldid=205431880