راهنمای کامل الگوهای طراحی در سی شارپ
آشنایی با الگوهای طراحی
الگوهای طراحی (Design Patterns) در واقع راهحلهای اثباتشدهای هستند که برای حل مشکلات تکراری در فرآیند توسعه نرمافزار به کار میروند. هدف اصلی از استفاده از این الگوها، افزایش قابلیت نگهداری، انعطافپذیری و سازماندهی بهتر کد است. این الگوها، در طول سالها و توسط برنامهنویسان و معماران نرمافزار حرفهای، به شکل یکسری دستورالعمل و ساختار مشخص جمعآوری شدهاند تا بتوانیم مسائل متداول را در فرایند طراحی و کدنویسی به شیوهای استاندارد و مؤثر حل کنیم.
هر الگویی ممکن است در یک زمینه خاص مانند ساخت اشیا، کنترل رفتار اجزا یا ساختاردهی بخشهای مختلف نرمافزار، بهترین کاربرد را داشته باشد. استفاده از این الگوها باعث میشود تیمهای توسعه بتوانند سریعتر ارتباط برقرار کرده و تصمیمات طراحی را بهتر توجیه کنند. الگوهای طراحی از یکسو سادگی را به ارمغان میآورند و از سوی دیگر به ما کمک میکنند از کدهای تکراری یا پیچیدگیهای غیرضروری جلوگیری کنیم.
کاربرد الگوهای طراحی در سی شارپ
در سی شارپ، ترکیب شدن الگوهای طراحی با قابلیتهای پیشرفته زبان مانند شیءگرایی، Genericها، LINQ و بسیاری از کتابخانههای غنی دیگر باعث میشود که بتوانیم به شکل مؤثری الگوها را پیادهسازی کنیم. با توجه به سینتکس ساده و روان سی شارپ، پیادهسازی الگوها اغلب کوتاهتر و خواناتر است و در نتیجه، یادگیری و توسعه نرمافزار با کیفیت بالا آسانتر میگردد.
بسیاری از Frameworkهای مایکروسافت نیز به شکل ضمنی یا صریح از این الگوها استفاده میکنند؛ بهعنوان نمونه ASP.NET Core، Entity Framework و WPF در بخشهایی از معماری خود از الگوهای طراحی بهره میبرند. این امر نشان میدهد که الگوهای طراحی نه تنها برای پروژههای شخصی و کوچک بلکه برای محصولات بزرگ سازمانی نیز ضروری هستند.
کاربرد الگوهای طراحی در سی شارپ را میتوان در سطوح مختلف کدنویسی مشاهده کرد؛ از لایههای پایگاه داده گرفته تا لاجیک تجاری و حتی طراحی رابطهای کاربری. یک الگوی مناسب میتواند سرعت توسعه را بهبود دهد، باگها را کاهش دهد و در طولانیمدت در هزینههای نگهداری کد صرفهجویی کند. ازاینرو، آشنایی با الگوهای مهم و کاربردی برای هر توسعهدهنده سی شارپ، یک نیاز اساسی محسوب میشود.
الگوی طراحی Builder
الگوی Builder به ما اجازه میدهد تا روند ساخت شیء پیچیده را از نمایش نهایی آن جدا کنیم. در بسیاری از مواقع، یک شیء دارای ساختار پیچیده و اجزای متعدد است که مقداردهی و تنظیم آنها بهشکل یکجا کار دشواری خواهد بود. با الگوی Builder میتوانیم مرحله به مرحله این ساخت را در یک کلاس جداگانه مدیریت کنیم و در پایان به یک شیء کاملاً آماده دست یابیم.
در سی شارپ، الگوی Builder میتواند به سادهسازی کدهای طولانی سازنده (Constructor) کمک کند. مثلاً وقتی با کلاسهای مدلی مواجهیم که خصوصیات زیادی دارند، به جای سازندگان شلوغ و متدهای طولانی تنظیم مقادیر، میتوانیم چندین Builder مختلف برای شرایط خاص داشته باشیم. این رویکرد خوانایی و نگهداری کد را افزایش میدهد.
برای مثال، فرض کنید میخواهیم یک شیء Person بسازیم که دارای خصوصیات متعددی مانند نام، نام خانوادگی، سن، آدرس و غیره است. میتوانیم یک کلاس Builder ایجاد کنیم که متدهایی مانند SetFirstName، SetLastName، SetAge و غیره را ارائه دهد. در نهایت با فراخوانی متد Build، شیء نهایی ساخته میشود.
دوره الگوی طراحی Builder در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Prototype
الگوی Prototype در مواقعی کاربرد دارد که ساخت اشیا با استفاده از فرایندهای پیچیده یا هزینهبر انجام میشود و ما نیاز داریم نمونههای جدیدی بر اساس یک نمونه موجود ایجاد کنیم. به بیان دیگر، به جای ساخت یک شیء از ابتدا، میتوان با کپی کردن نمونههای موجود، اشیای جدید را به سرعت تولید کرد.
در سی شارپ، استفاده از متد MemberwiseClone یا پیادهسازی الگوی Prototype به شکل سفارشی میتواند نیاز ما را رفع کند. این الگو بهخصوص در مواقعی که بخواهیم شیء با مقادیر اولیه مشابه اما تغییرات جزئی بسازیم، مفید است و به ما اجازه میدهد که سربار محاسباتی یا کدهای اضافی را کاهش دهیم.
تصور کنید یک شیء Report داریم که شامل تنظیمات مختلف، تصاویر و دادههای فراوان است. ایجاد یک نمونه جدید از این گزارش با تغییرات اندک اما با استفاده از سازنده طولانی، کار را دشوار میکند. با الگوی Prototype، تنها کافیست از نمونه موجود یک کپی ساخته و پارامترهای ضروری را تغییر دهیم.
دوره الگوی طراحی Prototype در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Abstract Factory
الگوی Abstract Factory به ما کمک میکند مجموعهای از اشیای مرتبط یا وابسته را بدون مشخص کردن کلاسهای دقیق آنها بسازیم. این الگو یک سطح انتزاعی بالاتر از Factory Method ارائه میدهد و معمولاً زمانی به کار میرود که چندین خانواده از محصولات داریم و میخواهیم به شکل پویا، یک خانواده مشخص از محصولات را بسازیم.
در سی شارپ، میتوانیم چندین اینترفیس یا کلاس مجرد داشته باشیم که عملیات ساخت اشیا را تعریف کرده و یک کلاس پیادهساز هر اینترفیس باشد تا کارخانه مربوط به یک خانواده محصول خاص را ایجاد کند. مزیت این الگو این است که تغییر یا افزودن خانواده جدیدی از محصولات، کمترین تأثیر را بر سایر قسمتهای کد دارد.
فرض کنید در یک برنامه فروشگاهی، دو نوع محصول دیجیتال و فیزیکی داریم و همچنین برای هر نوع محصول، روشهای پرداخت و حملونقل مخصوص تعریف شده است. با استفاده از Abstract Factory میتوانیم یک کارخانه مختص محصولات دیجیتال و یک کارخانه مختص محصولات فیزیکی داشته باشیم تا ساخت و مدیریت اشیا را تمیز و ساختیافته نگه داریم.
دوره الگوی طراحی Abstract Factory در سی شارپ (رایگان شرکت کنید)
الگوی طراحی State
الگوی State زمانی به کار میرود که شیء ما، رفتارش را بر اساس حالت داخلیاش تغییر میدهد. وقتی یک شیء در حالتهای مختلف رفتارهای متفاوت نشان میدهد، الگوی State مکانیزمی ارائه میدهد که این رفتارها را در کلاسهای جداگانهای به نام «حالت» قرار دهیم.
در سی شارپ، میتوانیم یک کلاس اصلی (Context) داشته باشیم که در درون خود یک مرجع به حالت جاری نگه میدارد و براساس رخدادها یا شرایط، این حالت را عوض کند. هر حالت هم پیادهسازی یک Interface یا کلاس پایه است که رفتار مشخصی را انجام میدهد.
برای نمونه، در یک وبسایت فروش بلیت، وضعیت سفارش میتواند در حالت «در حال بررسی»، «پرداخت شده»، «لغو شده» و... باشد. هر حالت، رفتار متفاوتی در متدهای مشترک مانند HandlePayment نشان میدهد. با الگوی State، این منطق بهجای درهمریزی در کلاس اصلی، بین کلاسهای مختلف توزیع میشود.
دوره الگوی طراحی State در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Memento
الگوی Memento برای ذخیره و بازیابی وضعیت داخلی یک شیء به کار میرود، بدون آنکه جزئیات پیادهسازی شیء در معرض دید قرار گیرد. این الگو مانند کارکرد Undo/Redo در نرمافزارها عمل میکند و امکان ذخیره و برگرداندن تغییرات وضعیت یک شیء را در زمانهای مختلف فراهم میسازد.
در سی شارپ، میتوانیم کلاس Memento را بهعنوان نگهدارنده اطلاعات وضعیت بسازیم و یک Originator داشته باشیم که وضعیت را داخل Memento قرار میدهد و از طریق Caretaker مدیریت میکند. الگوی Memento بهخصوص در برنامههای ویرایشی، بازیها یا هر موقعیتی که نیاز به برگرداندن حالت قبلی است، کاربرد فراوان دارد.
به عنوان مثال، در یک ویرایشگر متن، میتوان تغییرات متن کاربر را در مراحل مختلف نگه داشت تا هر زمان که لازم بود به حالت قبلی برگردیم. کلاس Memento جزئیات متن را ذخیره میکند؛ Caretaker نیز مجموعهای از Mementoها را مدیریت کرده و در صورت نیاز، کاربر به وضعیت قبلی بازمیگردد.
دوره الگوی طراحی Memento در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Template Method
الگوی Template Method روشی است برای تعریف اسکلت کلی یک الگوریتم در متدی در کلاس پایه و سپردن پیادهسازی برخی مراحل به کلاسهای فرزند. این الگو به ما اجازه میدهد ساختار اصلی الگوریتم را در متد تمپلیت قرار دهیم، اما جزئیات برخی گامها را زیرکلاسها پیادهسازی کنند.
در سی شارپ، میتوان متد Template را در کلاس پایه قرار داد و بعضی از مراحل را به شکل متدهای مجازی یا انتزاعی پیاده کرد. کلاسهای فرزند با بازنویسی این متدها، رفتار مورد نیازشان را اعمال میکنند. این کار موجب میشود تغییر در پیادهسازی برخی مراحل به راحتی انجام شود، بدون آنکه ساختار کلی الگوریتم به هم بریزد.
فرض کنید در یک برنامه باید دادهها را از منبعی بخوانیم، آن را اعتبارسنجی کنیم و سپس در دیتابیس ذخیره کنیم. گامهای اصلی این کار یکسان است اما نوع منبع داده یا روش اعتبارسنجی میتواند متفاوت باشد. با الگوی Template Method میتوان ساختار ثابت را حفظ کرد و تفاوتها را در کلاسهای فرزند پیاده نمود.
دوره الگوی طراحی Template Method در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Facade
الگوی Facade یک واسط سادهشده در اختیار ما قرار میدهد تا بتوانیم با سیستمی پیچیده تعامل داشته باشیم. این الگو با پنهان کردن جزئیات پیادهسازی و ارائه چند متد ساده، امکان استفاده راحتتر از یک سیستم بزرگ یا کتابخانه پیچیده را فراهم میکند.
در سی شارپ، میتوانیم یک کلاس فاساد ایجاد کنیم که متدهایی نظیر InitializeSystem، ProcessData و ShutdownSystem را ارائه دهد. در درون این متدها، کلاسهای پیچیدهتر و ماژولهای مختلف فراخوانی میشوند، اما مصرفکننده نهایی فقط با متدهای Facade سروکار دارد.
به عنوان نمونه، فرض کنید برنامهای داریم که از چندین سرویس خارجی استفاده میکند. در هر بار استفاده، باید توکن امنیتی بگیریم، لاگها را ثبت کنیم و داده را تبدیل نماییم. با الگوی Facade، این فرایندهای پیچیده را در یک متد ساده بستهبندی کرده و به توسعهدهنده نهایی فقط یک متد ارائه میکنیم.
دوره الگوی طراحی Facade در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Observer
الگوی Observer در سناریویی به کار میرود که یک شیء (Subject) نیاز دارد در صورت تغییر وضعیت خود، سایر اشیای وابسته (Observerها) را از تغییرات مطلع کند. این کار، مکانیزمی ایجاد میکند تا آبونمانها (مشترکان) بتوانند از رویدادهای مرتبط با Subject باخبر شوند و واکنش نشان دهند.
در سی شارپ، پیادهسازی الگوی Observer میتواند با استفاده از رویدادها (Events) یا واسطهای IObservable و IObserver انجام شود. موضوع اصلی (Subject) رویداد تعریف میکند و Observerها با ثبتنام در آن، از تغییرات مطلع میشوند. این الگو برای ساخت سیستمهای رویدادمحور بسیار پرکاربرد است.
در یک برنامه بورس، اگر قیمت سهام تغییر کند، باید به تمام کاربرانی که آن سهام را زیرنظر دارند اطلاع داده شود. سهام به عنوان Subject عمل میکند و کاربران به عنوان Observer. با هر تغییر قیمت، Subject یک رویداد فراخوانی میکند و کاربران مطلع میشوند.
دوره الگوی طراحی Observer در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Visitor
الگوی Visitor به ما اجازه میدهد عملیات جدیدی را روی مجموعهای از کلاسهای مختلف اعمال کنیم، بدون آنکه ساختار آن کلاسها را تغییر دهیم. در این الگو، یک کلاس بازدیدکننده (Visitor) ساخته میشود که متدهایی برای کار با انواع عناصر مختلف در اختیار دارد و هر عنصر میتواند با پذیرش این بازدیدکننده، عملیات مدنظر را اجرا کند.
در سی شارپ، معمولاً یک واسط IVisitor تعریف میکنیم که متدهایی نظیر VisitConcreteElementA و VisitConcreteElementB دارد. عناصر مختلف (Concrete Elements) متد Accept(IVisitor visitor) را پیادهسازی میکنند و در آن، متد مناسب از Visitor را فراخوانی میکنند.
به عنوان نمونه، در یک نرمافزار گرافیکی که دارای اشکال مختلف (دایره، مربع، مثلث و غیره) است، میتوان با الگوی Visitor عملکرد جدیدی مانند محاسبه محیط، مساحت یا رسم را اضافه کرد. کافیست Visitor مناسب را بسازیم تا تمام اشکال آن را بپذیرند و عملیات را روی خود اعمال کنند.
دوره الگوی طراحی Visitor در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Decorator
الگوی Decorator روشی برای افزودن رفتار جدید به اشیا به شکل پویا است، بدون اینکه در کلاس اصلی تغییری ایجاد شود. این الگو یک جایگزین منعطف برای ارثبری محسوب میشود؛ چرا که میتوانیم شیء اصلی را با لایههای جدیدی که عملکرد اضافه میکنند «تزیین» کنیم.
در سی شارپ، یک اینترفیس یا کلاس انتزاعی پایه تعریف میشود و یک Decorator همان اینترفیس یا کلاس را پیادهسازی کرده و در عین حال، یک ارجاع به شیء اصلی نگه میدارد. هر بار که متد یا ویژگی فراخوانی میشود، Decorator میتواند رفتار اضافهای قبل یا بعد از متد اصلی اعمال کند.
فرض کنید در یک برنامه ارسال پیام، نیاز است قبل از ارسال، پیام رمزنگاری و سپس فشرده شود. با الگوی Decorator میتوانیم یک شیء اصلی ارسال پیام بسازیم و بعد آن را با یک Decorator رمزنگار و سپس با یک Decorator فشردهساز تزیین کنیم. به این ترتیب، رفتارهای جدید بدون تغییر در کلاس اصلی اضافه میشوند.
دوره الگوی طراحی Decorator در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Bridge
الگوی Bridge به ما اجازه میدهد پیادهسازی (Implementation) را از انتزاع (Abstraction) جدا کنیم تا هر دو به شکل مستقل قابل تغییر باشند. این الگو بهویژه زمانی مفید است که دو بعد متفاوت از تغییرپذیری را بخواهیم مدیریت کنیم، بیآنکه تعداد کلاسها بیش از حد زیاد شود.
در سی شارپ، میتوان یک کلاس انتزاعی (Abstraction) تعریف کرد که یک ارجاع به اینترفیس یا کلاس پیادهساز (Implementor) دارد. متدهای Abstraction عملیات سطح بالا را ارائه میدهند و عملیات سطح پایین بر عهده Implementor است. بنابراین بهسادگی میتوان هر بخش را به شکل مستقل تغییر داد یا گسترش داد.
تصور کنید در یک برنامه پخش فایلهای صوتی، بخواهیم فایل را از دیسک محلی یا اینترنت بخوانیم و همچنین فرمتهای مختلف MP3، WAV و... را اجرا کنیم. یک Abstraction میتواند کار «پخش فایل» را مدیریت کند و یک Implementor میتواند مسئولیت «نحوه دسترسی به فایل» را برعهده بگیرد. با الگوی Bridge، اضافه کردن راههای جدید پخش یا منابع جدید به راحتی انجام میشود.
دوره الگوی طراحی Bridge در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Iterator
الگوی Iterator روشی برای پیمایش عناصر مجموعههای مختلف (مانند آرایه، لیست یا درخت) ارائه میدهد، بدون آنکه جزئیات داخلی مجموعه افشا شود. این الگو با جدا کردن منطق پیمایش از ساختار واقعی داده، کد را تمیزتر و ماژولارتر میکند.
در سی شارپ، از امکانات داخلی مانند IEnumerable و IEnumerator استفاده میکنیم تا الگوی Iterator را پیادهسازی نماییم. همچنین میتوان از کلمه کلیدی yield برای سادهسازی نگارش Iterator بهره برد. این قابلیتها پیادهسازی الگوی Iterator را بسیار راحت میکنند.
برای مثال، اگر یک ساختار داده سفارشی مانند LinkedList یا درخت دودویی داشته باشیم و بخواهیم عناصر آن را به شیوهای یکنواخت پیمایش کنیم، میتوانیم یک Iterator بسازیم تا مرحله به مرحله عنصر بعدی را برگرداند. به این ترتیب، مدیریت و استفاده از ساختار داده آسانتر میشود.
دوره الگوی طراحی Iterator در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Factory Method
الگوی Factory Method یک ساختار برای تعریف یک متد سازنده در کلاس پایه فراهم میکند، اما تصمیم درباره اینکه کدام کلاس دقیق ساخته شود را به زیرکلاسها واگذار میکند. این کار باعث میشود سازنده در یک نقطه متمرکز باشد اما نوع نهایی شیء در زمان اجرا یا توسط زیرکلاس مشخص شود.
در سی شارپ، یک کلاس پایه میتواند متد ساخت انتزاعی داشته باشد و زیرکلاسها این متد را پیادهسازی کنند تا کلاسهای مختلف بسازند. این الگو بهخصوص زمانی مفید است که بخواهیم با توجه به شرایط مختلف، یکی از چندین نوع محصول را ایجاد کنیم.
برای نمونه، در یک برنامه نموداری، ممکن است انواع مختلف چارت (ستونی، دایرهای، خطی) مورد نیاز باشد. یک زیرکلاس Factory میتواند چارت ستونی بسازد و دیگری چارت دایرهای. به این ترتیب، کد اصلی درگیر جزئیات ایجاد هر چارت نیست و فقط از متد Factory استفاده میکند.
دوره الگوی طراحی Factory Method در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Composite
الگوی Composite اجازه میدهد مجموعهای از اشیا را در قالب یک ساختار درختی سازماندهی کنیم و با یک شیء ساده و گروهی از اشیا به شکلی یکنواخت رفتار کنیم. به عبارتی، میتوانیم با اشیای منفرد و اشیای مرکب بدون تفاوت در روش دسترسی و مدیریت برخورد کنیم.
در سی شارپ، یک اینترفیس یا کلاس پایه تعریف میکنیم که عملیاتهای مشترک بین شیء ساده (Leaf) و شیء مرکب (Composite) را مشخص میکند. کلاس Composite فهرستی از اشیای فرزند را نگهداری میکند و متدهایی مانند Operation را با فراخوانی روی تمام فرزندان پیاده میکند.
به عنوان مثال، در واسط کاربری گرافیکی (GUI)، یک پنجره میتواند شامل دکمه، لیبل، و حتی پنجرههای فرزند باشد. هر کدام از این موارد یک عنصر به شمار میآید. با الگوی Composite، میتوان مدیریت رویداد کلیک یا عملیات رسم را به شکل واحدی برای تمام عناصر اعمال کرد.
دوره الگوی طراحی Composite در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Flyweight
الگوی Flyweight برای بهینهسازی مصرف حافظه در شرایطی به کار میرود که تعداد بسیار زیادی شیء مشابه وجود دارد. ایده اصلی در این الگو تفکیک دادههای درونی و بیرونی شیء است؛ دادههای درونی در شیء Flyweight نگهداری شده و بین همه نمونهها بهاشتراک گذاشته میشوند. دادههای بیرونی هم خارج از آن ذخیره میشوند.
در سی شارپ، میتوان یک کلاس Flyweight داشت که خصوصیات ثابت اشیا را ذخیره میکند و از یک Factory برای مدیریت ساخت آنها استفاده کرد. اگر یک Flyweight با مشخصات مورد نظر از قبل وجود داشته باشد، همان را برمیگردانیم و در غیر این صورت نمونه جدید میسازیم.
یک مثال رایج، نمایش کاراکترهای متن در یک ویرایشگر است. هر کاراکتر اطلاعاتی مانند شکل قلم دارد (دادههای درونی) که در یک Flyweight مشترک نگهداری میشود و دادههای بیرونی مانند موقعیت و اندازه، جداگانه برای هر کاراکتر ذخیره میشود. با این کار، هزاران کاراکتر A را میتوان با یک Flyweight واحد نمایش داد.
دوره الگوی طراحی Flyweight در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Command
الگوی Command درخواستها را در قالب اشیا کپسوله میکند. این رویکرد باعث میشود ما بتوانیم درخواستها را در صف قرار دهیم، لغو کنیم یا عملیات را در زمانی دیگر اجرا کنیم. همچنین برای ساخت عملکردهایی مانند Undo/Redo ساختار بسیار مناسبی فراهم میکند.
در سی شارپ، میتوان اینترفیس یا کلاس انتزاعی Command را با متدهایی مانند Execute و در صورت نیاز Undo تعریف کرد. هر Command روی یک دریافتکننده (Receiver) خاص عمل میکند. سپس میتوان این Commandها را در بخشهای مختلف برنامه، از جمله رویدادهای دکمهها در رابط کاربری، فراخوانی کرد.
به عنوان مثال، در یک برنامه ویرایش متن، عملیات «کپی»، «چسباندن» و «حذف» را میتوان به شکل Commandهای مجزا تعریف کرد. وقتی کاربر این دستورات را اجرا میکند، Command مناسب فراخوانی شده و عمل انجام میگیرد. قابلیت Undo نیز با ذخیره Commandهای اجرا شده در یک پشته امکانپذیر است.
دوره الگوی طراحی Command در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Adapter
الگوی Adapter دو رابط ناسازگار را به یکدیگر متصل میکند. اگر کلاسی داریم که یک رابط خاص انتظار دارد اما یک کلاس دیگر رابط متفاوتی ارائه میدهد، میتوان با الگوی Adapter بین این دو واسطه ایجاد کرد تا کلاس ناسازگار «سازگار» شود.
در سی شارپ، یک کلاس Adapter تعریف میشود که اینترفیس مورد انتظار کلاینت را پیادهسازی میکند و ارجاعی به کلاس ناسازگار دارد. با این کار، هر بار که متد کلاینت فراخوانی میشود، Adapter آن را به روش مناسب به کلاس ناسازگار منتقل میکند.
به عنوان مثال، اگر در کد ما همه چیز با فرمت XML کار میکند اما کتابخانهای موجود است که فقط با JSON سروکار دارد، میتوانیم با الگوی Adapter داده JSON را قبل از فراخوانی متدهای کتابخانه مقصد به فرمت XML تبدیل کنیم. به این شکل، بدون نیاز به تغییر در کد اصلی یا کتابخانه، مشکل ناسازگاری حل میشود.
دوره الگوی طراحی Adapter در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Interpreter
الگوی Interpreter برای تعریف گرامر یک زبان ساده و تفسیر جملات آن زبان استفاده میشود. اگر نیاز به یک زبان محدود (مثلاً برای اعمال ریاضی ساده، شروط یا پرسوجوها) داشته باشیم، با الگوی Interpreter میتوان مجموعهای از کلاسها ساخت که هر کدام نماینده یک قاعده گرامری در آن زبان باشند.
در سی شارپ، میتوان یک کلاس انتزاعی برای تعریف قواعد داشت و کلاسهای فرزند را برای قاعدههای خاص (مثل جمع، ضرب یا یک عبارت ترمینال) ایجاد کرد. هر کلاس متد Interpret را پیادهسازی میکند و ورودی را تحلیل کرده و خروجی مورد نظر را برمیگرداند.
برای مثال، ساخت یک ماشین حساب ساده با الگوی Interpreter انجام میشود. ابتدا یک درخت نحوی (Parse Tree) از عبارت ریاضی (مانند ۳+۵*۲) میسازیم و سپس با فراخوانیهای بازگشتی متد Interpret در هر گره، نتیجه نهایی محاسبه میشود.
دوره الگوی طراحی Interpreter در سی شارپ (رایگان شرکت کنید)
الگوی طراحی Proxy
الگوی Proxy یک نماینده یا واسطه برای دسترسی به شیء اصلی است. این واسطه میتواند مسئول کنترل دسترسی، ایجاد تأخیر در مقداردهی، لاگ گرفتن از دسترسی یا هر عملیات دیگر باشد که قبل یا بعد از فراخوانیهای واقعی روی شیء اصلی مورد نیاز است. به این ترتیب، میتوان قابلیتهای اضافی را بدون تغییر در کلاس اصلی فراهم کرد.
در سی شارپ، معمولاً یک اینترفیس یا کلاس انتزاعی پایه پیاده میکنیم که هم شیء اصلی و هم Proxy از آن تبعیت میکنند. داخل Proxy، یک نمونه از کلاس اصلی نگهداری میشود و فراخوانیهای متد به این شیء اصلی انتقال مییابد؛ اما قبل یا بعد از آن، هر کار اضافی مورد نیاز (مثلاً بررسی سطح دسترسی) انجام میشود.
فرض کنید در یک سامانه مدیریت فایل، میخواهیم پیش از هر عملیات خواندن یا نوشتن، مجوزهای کاربر را بررسی کنیم. یک Proxy میتواند این بررسی را انجام دهد و در صورت داشتن مجوز، عملیات را روی فایل اصلی انجام دهد. به این شکل، کنترل امنیتی یا حتی کش کردن دادهها نیز پیادهسازی آسانتری خواهد داشت.