الکتروهایو

هوش مصنوعی / الکترونیک / برنامه‌نویسی

2 پاسخ

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

    1. با سلام و عرض ادب خدمت شما بزرگوار جناب مهندس نادری عزیز از اساتید برنامه نویسی بسیار با دانش و مطلع. خوشحالم که مطلب مورد توجه شما بوده است.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

الگوی Adapter در الگوهای طراحی Structural به همراه کد

الگوی Adapter در الگوهای طراحی Structural به همراه کد - مجله الکتروهایو
در این مقاله می‌خوانید:

زمان تخمینی مطالعه: 0 دقیقه

الگوی Adapter یک الگوی ساختاری(Structural) است که به اینترفیس یک کلاس موجود اجازه می‌دهد تا به عنوان اینترفیس کلاس دیگر استفاده شود. در واقع این الگوها باعث به وجود آمدن پلی بین دو اینترفیس ناسازگار می‌شوند. الگویAdapter که با نام Wrapper(پوشاننده) نیز شناخته می‌شود به اشیا با رابط‌های ناسازگار اجازه همکاری می‌دهد. این الگو شامل یک کلاس واحد است که به عنوان آداپتور شناخته می‌شود، که مسئول پیوستن به عملکردهای اینترفیس‌های مستقل یا ناسازگار است.

Adapter design pattern

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

The structure of the app before integration with the analytics library
در حالت کلی از کتابخانه تجزیه و تحلیل «همانطوری که هستند» استفاده کنید، زیرا انتظار می‌رود داده‌ها در قالبی ناسازگار با برنامه شما باشد.

در برنامه خود می‌توانید کتابخانه مورد استفاده را برای کار با XML تغییر دهید. با این حال، این موضوع ممکن است برخی از کدهای موجود را که به کتابخانه متکی هستند، خراب کند. و بدتر از آن، ممکن است در وهله اول به کد منبع کتابخانه دسترسی نداشته باشید، که این رویکرد را غیر ممکن می‌کند. پس چه باید کرد؟؟؟

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

آداپتورها نه تنها می‌توانند داده‌ها را به فرمت‌های مختلف تبدیل کنند، بلکه می‌توانند به اشیاء با اینترفیس‌های مختلف کمک کنند. در اینجا نحوه عملکرد آنها آمده است:

  1. آداپتور یک اینترفیس، سازگار با یکی از اشیاء موجود را دریافت می‌کند.
  2. با استفاده از این اینترفیس، شی موجود می‌تواند با خیال راحت متدهای الگوی Adapter را فراخوانی کند.
  3. پس از دریافت فراخوانی، آداپتور درخواست را به شی دوم ارسال می‌کند، اما در قالب و ترتیبی که شی دوم با آن سازگار است و انتظار دارد.

گاهی اوقات حتی می‌توان آداپتوری دو طرفه ایجاد کرد که بتواند فراخوانی‌ها را در هر دو جهت تبدیل کند.

Adapter's solution

اجازه دهید مجددا به برنامه بازار سهام خود برگردیم. برای حل معضل فرمت‌های ناسازگار، می‌توانید آداپتورهای XML-to-JSON را برای هر کلاسی از کتابخانه تحلیلی که کد شما مستقیماً با آن کار می‌کند ایجاد کنید. سپس کد خود را طوری تنظیم می‌کنید که فقط از طریق این آداپتورها با کتابخانه ارتباط برقرار کند. هنگامی که یک آداپتور فراخوانی را دریافت می‌کند، داده‌های XML ورودی را به یک ساختار JSON ترجمه می‌کند و فراخوانی را به روش‌های مناسب یک شی قابل تحلیل پیچیده ارسال می‌کند.

نمونه قابل قیاس در دنیای واقعی

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

The Adapter pattern example
یک چمدان قبل و بعد از سفرهای متعدد به خارج از کشور.

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

ساختار الگوی Adapter

در این بخش به بررسی ساختار الگوی آداپتور می‌پردازیم و پیاده‌سازی آن را به صورت UML خواهیم دید. در حالت کلی الگوی Adapter دارای دو مدل ساختار متفاوت است که در ادامه هر دو مدل را بررسی خواهیم کرد.

– آداپتور شی(Object Adapter)

این پیاده سازی از اصل ترکیب شی استفاده می‌کند: آداپتور اینترفیس یک شی را پیاده‌سازی کرده و شی دیگر را می‌پوشاند. این مدل را می‌توان در تمام زبان‌های برنامه‌نویسی رایج پیاده‌سازی کرد.

  • گام 1: در اینجا Client کلاسی است که شامل منطق تجاری موجود برنامه است.
  • گام 2: اینترفیس Client پروتکلی را توصیف می‌کند که سایر کلاس‌ها باید از آن پیروی کنند تا بتوانند با کد Client همکاری کنند.
  • گام 3: کلاس Service یک کلاس مفید است. کلاینت نمی‌تواند مستقیماً از این کلاس استفاده کند زیرا دارای یک اینترفیس ناسازگار است.
  • گام 4: در اینجا Adapter کلاسی است که می‌تواند هم با کلاینت و هم با خود سرویس کار کند: اینترفیس مشتری را پیاد‌ه‌سازی می‌کند، در حالی که شی سرویس را می‌پوشاند. آداپتور فراخوانی‌ها را از طریق اینترفیس کلاینت دریافت می‌کند و آنها را به فراخوانی‌هایی با شیء سرویس پوشیده شده در قالبی که قابل درک است ترجمه می‌کند.
  • گام 5: کد کلاینت تا زمانی که از طریق اینترفیس کلاینت با آداپتور کار می‌کند با کلاس concrete آداپتور همراه نمی‌شود. به لطف این موضوع، می‌توانید انواع جدیدی از آداپتورها را بدون شکستن کد کلاینت موجود وارد برنامه کنید. این می‌تواند زمانی مفید باشد که اینترفیس کلاس سرویس تغییر کند یا جایگزین شود: شما فقط می‌توانید یک کلاس آداپتور جدید بدون تغییر کد کلاینت ایجاد کنید.

– آداپتور کلاس(Class Adapter)

این پیاده‌سازی از وراثت استفاده می‌کند: آداپتور اینترفیس‌ها را از هر دو شی به طور همزمان به ارث می‌برد. توجه داشته باشید که این رویکرد فقط در زبان‌های برنامه‌نویسی که از وراثت چندگانه پشتیبانی می‌کنند، مانند ++C قابل پیاده‌سازی است.

Adapter design pattern (class adapter)

آداپتور کلاس(Class Adapter) نیازی به پوشش دادن هیچ شیئی ندارد زیرا رفتارها را هم از کلاینت و هم از سرویس به ارث می‌برد. معمولا انطباق(Adaptation) در روش‌های نادیده گرفته شده(Overridden) اتفاق می‌افتد. آداپتور حاصل می‌تواند به جای یک کلاس کلاینت موجود استفاده شود.

شبه کد(Pseudocode)

این مثال از الگوی Adapter مبتنی بر درگیری کلاسیک موجود مابین میخ‎‌های مربعی(square peg) و سوراخ‌های گرد است.

Structure of the Adapter pattern example
تطبیق میخ‌های مربعی با سوراخ‌های گرد.

آداپتور وانمود می‌کند که یک میخ گرد است که شعاع آن برابر با نیمی از قطر مربع است (به عبارت دیگر، شعاع کوچک‌ترین دایره‌ای که می‌تواند میخ مربعی را در خود جای دهد).

// Say you have two classes with compatible interfaces:
// RoundHole and RoundPeg.
class RoundHole is
    constructor RoundHole(radius) { ... }

    method getRadius() is
        // Return the radius of the hole.

    method fits(peg: RoundPeg) is
        return this.getRadius() >= peg.getRadius()

class RoundPeg is
    constructor RoundPeg(radius) { ... }

    method getRadius() is
        // Return the radius of the peg.


// But there's an incompatible class: SquarePeg.
class SquarePeg is
    constructor SquarePeg(width) { ... }

    method getWidth() is
        // Return the square peg width.


// An adapter class lets you fit square pegs into round holes.
// It extends the RoundPeg class to let the adapter objects act
// as round pegs.
class SquarePegAdapter extends RoundPeg is
    // In reality, the adapter contains an instance of the
    // SquarePeg class.
    private field peg: SquarePeg

    constructor SquarePegAdapter(peg: SquarePeg) is
        this.peg = peg

    method getRadius() is
        // The adapter pretends that it's a round peg with a
        // radius that could fit the square peg that the adapter
        // actually wraps.
        return peg.getWidth() * Math.sqrt(2) / 2


// Somewhere in client code.
hole = new RoundHole(5)
rpeg = new RoundPeg(5)
hole.fits(rpeg) // true

small_sqpeg = new SquarePeg(5)
large_sqpeg = new SquarePeg(10)
hole.fits(small_sqpeg) // this won't compile (incompatible types)

small_sqpeg_adapter = new SquarePegAdapter(small_sqpeg)
large_sqpeg_adapter = new SquarePegAdapter(large_sqpeg)
hole.fits(small_sqpeg_adapter) // true
hole.fits(large_sqpeg_adapter) // false

قابلیت‌ها و کاربرد‌ها

  • از کلاس Adapter زمانی استفاده کنید که می‌خواهید از کلاسی موجود استفاده کنید اما در این هنگام اینترفیس آن با بقیه کد شما ناسازگار باشد. در این حالت الگوی Adapter به شما امکان می‌دهد یک کلاس لایه میانی ایجاد کنید که به عنوان مترجم بین کد شما و یک کلاس قدیمی، یک کلاس شخص ثالث یا هر کلاس دیگری با اینترفیس کاربری عجیب و غریب عمل می‌کند.
  • هنگامی که می‌خواهید چندین زیر کلاس موجود را که فاقد برخی عملکردهای مشترک هستند و نمی‌توان آنها را به سوپرکلاس اضافه کرد، مجدداً استفاده کنید، از الگوی Adapter استفاده کنید. شما می‌توانید هر زیر کلاس را گسترش داده و عملکرد فراموش شده را در کلاس‌های فرزند جدید قرار دهید. با این حال، باید کد را در تمام این کلاس‌های جدید کپی کنید، که به نظر کار درستی نیست.

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

نحوه پیاده‌سازی

  1. مطمئن شوید که حداقل دو کلاس با اینترفیس‌های ناسازگار دارید:
    • یک کلاس سرویس مفید که نمی‌توانید آن را تغییر دهید (اغلب کلاس‌های شخص ثالث، قدیمی یا با وابستگی‌های موجود زیاد).
    • یک یا چند کلاس مشتری که بوسیله استفاده از کلاس سرویس سود می‌برند.
  2. اینترفیس مشتری را اعلان کنید و نحوه ارتباط مشتریان با سرویس را شرح دهید.
  3. کلاس آداپتور را ایجاد کنید و کاری کنید که آن از اینترفیس مشتری پیروی کند. فعلا تمام متدها را خالی بگذارید.
  4. یک فیلد به کلاس آداپتور اضافه کنید تا یک رفرنس در شیء سرویس ذخیره شود. روش معمول این است که این فیلد را از طریق سازنده مقداردهی اولیه کنید، اما گاهی اوقات هنگام فراخوانی متدهای آن، انتقال آن به آداپتور راحت‌تر است.
  5. یکی یکی تمام متدهای اینترفیس کلاینت را در کلاس آداپتور پیاده‌سازی کنید. آداپتور باید بیشتر کار واقعی را به شیء سرویس واگذار کند و فقط اینترفیس یا تبدیل فرمت داده را مدیریت کند.
  6. مشتریان باید از آداپتور بوسیله اینترفیس مشتری استفاده کنند. این موضوع به شما امکان می‌دهد آداپتورها را بدون تأثیر بر روی کد مشتری تغییر دهید یا گسترش دهید.

مزایا و معایب الگوی Adapter

این الگوی طراحی دارای مزایا و معایبی به شرح زیر است:

– مزایا

  • اصل مسئولیت واحد: می‌توانید اینترفیس یا کد تبدیل داده را از منطق تجاری اصلی برنامه جدا کنید.
  • اصل باز/بسته: شما می‌توانید انواع جدیدی از آداپتورها را بدون شکستن کد مشتری موجود به برنامه معرفی کنید، به شرطی که از طریق اینترفیس مشتری با آداپتورها کار کنند.

معایب

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

ارتباط با الگوهای دیگر

  • الگوی Bridge معمولاً از قبل طراحی می‌شود و به شما امکان می‌دهد بخش‌هایی از یک برنامه را مستقل از یکدیگر توسعه دهید. از سوی دیگر، الگوی Adapter معمولاً با یک برنامه موجود استفاده می‌شود تا برخی از کلاس‌های ناسازگار بتوانند به خوبی با هم کار کنند.
  • آداپتور یک رابط کاملا متفاوت برای دسترسی به یک شی موجود فراهم می‌کند. از طرف دیگر، با الگوی Decorator اینترفیس ثابت بوده و یا گسترش می‌یابد. علاوه بر این، Decorator از ترکیب بازگشتی پشتیبانی می‌کند، که با استفاده از آداپتور امکان پذیر نیست.
  • با آداپتور شما از طریق اینترفیس‌های مختلف به یک شی موجود دسترسی پیدا می‌کنید. با الگوی Proxy، اینترفیس ثابت می‌ماند. با Decorator شما از طریق یک اینترفیس پیشرفته به شی دسترسی دارید.
  • الگوی Facade یک اینترفیس جدید برای اشیاء موجود تعریف می‌کند، در حالی که الگوی Adapter سعی می‌کند رابط موجود را قابل استفاده کند. آداپتور معمولاً فقط یک شی را می‌پوشاند، در حالی که Facade با یک زیر سیستم کامل از اشیا کار می‌کند.
  • الگوهای Bridge، الگوی State و الگوی Strategy (و تا حدی آداپتور) ساختارهای بسیار مشابهی دارند. در واقع، همه این الگوها بر اساس ترکیب‌بندی هستند که کار را به اشیاء دیگر واگذار می‌کند. با این حال، همه آنها مشکلات مختلفی را حل می‌کنند. یک الگو فقط دستور العملی برای ساختار کد شما به روشی خاص نیست. همچنین می‌تواند مشکلی را که الگو حل می‌کند با توسعه‌دهندگان دیگر در میان بگذارد.

نمونه کد الگوی Adapter

لوگو الکتروهایو

الکتروهایو در خدمت مخاطبان عزیز می‌باشد. ما در تیم الکتروهایو در تلاش برای تهیه مقالات و مطالب به روز هستیم. لطفا برای مطالب و مقالات بیشتر با ما همراه باشید.

مطالب مرتبط:

داده‌های اسمی Nominal Data - الکتروهایو

داده‌های اسمی Nominal Data چیست؟

داده‌های اسمی(Nominal Data) یکی از اساسی‌ترین انواع داده‌ها در تجزیه و تحلیل داده‌ها است. شناسایی و تفسیر آن در بسیاری از زمینه‌ها از جمله آمار، علوم کامپیوتر، روانشناسی و بازاریابی ضروری است. این مقاله ویژگی‌ها، کاربردها و تفاوت‌های داده‌های اسمی

ادامه مطلب »
مقدمه‌ای بر ژوپیتر نوت‌بوک Jupiter Notebook - سایت الکتروهایو

مقدمه‌ای بر ژوپیتر نوت‌بوک Jupiter Notebook برای یادگیری ماشین

ژوپیتر نوت‌بوک(Jupyter Notebook) یک پلتفرم وب منبع باز است که به توسعه دهندگان اجازه می‌دهد اسنادی را ایجاد و به اشتراک بگذارند که شامل متن روایت، کد زنده، تجسم‌ها و معادلات است. این پلتفرم مبتنی بر تجسم داده‌ها، تمیز کردن

ادامه مطلب »
تفاوت تصویر، عکس و نگاره چیست؟ - سایت الکتروهایو

تفاوت تصویر، عکس و نگاره چیست؟

امروزه، اکثر مردم هنگام بحث در مورد نمایش بصری یک شی در رایانه، تفاوت تصویر، عکس و نگاره را نمی‌دانند و آنها را مترادف هم در نظر می‌گیرند. اما برای ابهام هر یک از این موارد را به صورت زیر

ادامه مطلب »
خزنده وب Web Crawler چیست؟ - سایت الکتروهایو

خزنده وب Web Crawler چیست؟

تعریف خزنده وب خزنده وب یک ربات موتور جستجوی دیجیتال است که از کپی و ابرداده(Metadata) برای کشف و فهرست‌بندی صفحات سایت استفاده می‌کند. این مفهوم همچنین به عنوان ربات عنکبوتی(اسپایدر) نیز نامیده می‌شود، وب کراولرها در وب جهانی (از

ادامه مطلب »
مفهوم SIEM (مدیریت رویداد و امنیت اطلاعات) چیست؟

مفهوم SIEM (مدیریت رویداد و امنیت اطلاعات) چیست؟

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

ادامه مطلب »
داده‌های اسمی Nominal Data - الکتروهایو

داده‌های اسمی Nominal Data چیست؟

داده‌های اسمی(Nominal Data) یکی از اساسی‌ترین انواع داده‌ها در تجزیه و تحلیل داده‌ها است. شناسایی ...

حاشیه‌نویسی متن در هوش مصنوعی - سایت الکتروهایو

حاشیه‌نویسی متن در هوش مصنوعی

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

هوش مصنوعی در باستان شناسی و کاربردهای آن - سایت الکتروهایو

هوش مصنوعی در باستان شناسی چه کاربردهای می‌تواند داشته باشد؟

مکان‌های باستان‌شناسی ممکن است ثابت باشند، اما فرهنگ‌هایی که آنها را تولید کرده‌اند، پویا و ...

با الگوریتم تشخیص اشیاء FCOS آشنا شوید - سایت الکتروهایو

با الگوریتم تشخیص اشیاء FCOS آشنا شوید: تشخیص اشیاء تک مرحله‌ای کاملاً کانولوشنال

تشخیص اشیاء یک کار مهم در بینایی کامپیوتر است که با رسم کادرهای محدود کننده ...

تصویربرداری چند طیفی، دیدی جدید فراسوی نور مرئی - سایت الکتروهایو

تصویربرداری چند طیفی، دیدی جدید فراسوی نور مرئی

تصویربرداری چند طیفی تکنیکی است که نور را در طیف وسیعی از باندهای طیفی، فراتر ...