امین احسان
امین احسان
خواندن ۴ دقیقه·۲ سال پیش

الگوی طراحی آداپتور - Adapter Design Pattern

Adapter Design Pattern
Adapter Design Pattern


بررسی

الگوی طراحی Adapter به اشیا با Interface‌ های ناسازگار اجازه همکاری می‌دهد.


مشکل

تصور کنید که در حال ایجاد یک برنامه نظارت بر بازار سهام هستید، این برنامه داده‌های سهام را از چندین منبع در قالب XML بارگیری می‌کند و سپس نمودارها و دیاگرام‌های زیبا را برای کاربر نمایش می‌دهد.

در برخی مواقع تصمیم می‌گیرید با ادغام یک کتابخانه تحلیلی هوشمند (شخص ثالث) برنامه را بهبود ببخشید، اما یک نکته وجود دارد، کتابخانه فقط با داده‌ها در قالب JSON کار می‌کند.

می‌توانید کتابخانه را برای کار با قالب XML تغییر دهید. با این حال این کار ممکن است برخی از کدهای موجود را که به کتابخانه متکی است خراب کند و بدتر از آن ممکن است به کدهای منبع کتابخانه دسترسی نداشته باشید که در این صورت تغییر دادن کتابخانه روشی غیر ممکن خواهد بود.


راه حل

می‌توانید یک الگوی Adapter ایجاد کنید، این الگو Interface‌ یک شی را، به گونه‌ای تغییر می‌دهد که یک شی دیگر، بتواند آن را درک کند.

در واقع Adapter بر روی یکی از اشیا، روکشی را قرار می‌دهد تا پیچیدگی تغییر را در پشت صحنه پنهان کند. (شی حتی از وجود این روکش آگاه نمی‌شود)

برای مثال می‌توانید یک شی‌ را که بر حسب متر و کیلومتر کار می‌کند، با قرار دادن روکش Adapter طوری بپیچید که تمام داده‌ها به واحدهایی مانند فوت و مایل تبدیل شوند.

آن‌ها نه تنها می‌توانند داده‌ها را به فرمت‌های مختلف تبدیل کنند، بلکه می‌تواند به همکاری و ارتباط اشیا با Interface‌ های مختلف کمک کنند.

یک Interface‌ سازگار با یکی از اشیا موجود را دریافت می‌کند.

با استفاده از این Interface‌ شی موجود می‌تواند، با خیال راحت متدهای Adapter را فراخوانی نماید. پس از دریافت فراخوانی، Adapter درخواست را به شی دوم ارسال می‌کند، اما در قالب و ترتیبی که شی دوم انتظار دارد.

گاهی اوقات حتی می‌توان یک Adapter دو طرفه ایجاد کرد، که توانایی فراخوانی‌ها را در هر دو جهت در قالب مورد نظر را داشته باشد.

بیایید به برنامه بازار سهام برگردیم، برای حل مشکل فرمت‌های ناسازگار می‌توانید، Adapter های XML-to-JSON را برای هر کلاسی از کتابخانه تحلیلی که کد شما مستقیما با آن کار می‌کند ایجاد کنید.

سپس کد خود را، طوری تنظیم کنید که فقط از طریق این Adapter ها با کتابخانه ارتباط برقرار کنند.

هنگامی که یک Adapter فراخوانی می‌شود، داده‌های XML ورودی را، به یک ساختار JSON تبدیل می‌کند و فراخوانی را به روش‌های مناسب تر به شی تحلیلگر ارسال می‌کند.


ساختار

  • بخش Client شامل Business Logic موجود در برنامه است.
  • بخش Interface Client پروتکلی را توصیف می‌کند که سایر کلاس ها باید از آن پیروی کنند تا بتوانند با کد کلاینت همکاری کنند.
  • بخشی Service معمولا ناسازگار (شخص ثالث یا قدیمی) که کلاینت نمی‌تواند مستقیما از این کلاس استفاده کند. (زیرا دارای یک Interface‌ ناسازگار است)
  • بخشی Adapter می‌تواند با هر دو بخش دیگر کار کند. Interface‌ مشترک را پیاده سازی می کند و در حالی که شی Service را در بر گرفته است، درخواست‌ها را از طریق Interface‌ Adapter دریافت و آنها را به درخواست‌هایی که برای بخش دیگر قابل درک است ترجمه می‌کند.
  • کد کلاینت تا زمانی که از طریق Interface‌ Client کار کند، با کلاس Adapter جفت نمی‌شود. که می‌توان به کمک آن انواع جدیدی از Adapter ها را بدون تغییر در کد کلاینت، به برنامه اضافه کرد. زمانی مفید است که Interface‌ Service تغییر کند. (شما فقط کافیست یک کلاس Adapter جدید بدون تغییر در کد Client ایجاد کنید)


نمونه

هنگامی که برای اولین بار از کشوری به کشور دیگر سفر می‌کنید، ممکن است هنگام تلاش برای شارژ لپ‌تاپ خود غافلگیر شوید، استانداردهای پریز برق در کشورهای مختلف متفاوت است. اما مشکل را می‌توان با استفاده از یک Adapter برقی که دارای تبدیل سوکت می‌باشد حل کرد.


نتیجه

از Adapter استفاده می‌شود، وقتی که می‌خواهید از یک کلاس موجود استفاده کنید، اما Interface‌ آن با بقیه کد شما سازگار نیست.

الگوی Adapter به شما امکان می‌دهد یک کلاس لایه میانی ایجاد کنید که، به عنوان مترجم بین کد شما و (یک کلاس شخص ثالث) یا هر کلاس دیگری با Interface‌ متفاوت، عمل می‌کند.

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

شما می‌توانید هر زیر کلاس را گسترش دهید و عملکرد را در هر کلاس‌ فرزند جدید، قرار دهید. با این حال باید، کد را در تمام این کلاس‌ها کپی کنید، که اشتباه است. راه حل درست تر قرار دادن عملکردها در یک کلاس Adapter می‌باشد.

سپس اشیا با عملکردهای نداشته را در داخل Adapter قرار می‌دهید تا عملکردهای مورد نیاز به صورت ‌Dynamic اضافه شوند. برای این کار کلاس‌های هدف باید یک Interface‌ مشترک داشته باشند و Adapter باید از آن Interface‌ پیروی کند. این رویکرد بسیار شبیه به الگوی Decorator است.


linkedin.com/in/AminEhsan

github.com/AminEhsan

مهندسی نرم افزاربرنامه نویسیالگوی طراحیdesign patternadapter
مجموعه مقالات با هدف تحلیل و بررسی علوم کامپیوتر
شاید از این پست‌ها خوشتان بیاید