HamidReza Ireh

حمیدرضا ایره

HamidReza Ireh

حمیدرضا ایره

حوزه: Object / Class
هدف: Structural
نقش الگو
همان گونه که از اسم این الگو مشخص است، هنگامی که دو کلاس واسط(Interface) های غیرمرتبط با یکدیگر داشته باشند این الگو واسط یکی را به دیگری تبدیل می‌کند که بتوانند با یکدیگر ارتباط برقرار کند. از این الگو که یک الگوی ساختاری است زمانی استفاده می‌شود که بخواهیم در یک برنامه، دو کلاس غیرمرتبط با یکدیگر کار کنند. این الگو در برنامه‌هایی که از کلاس‌های آماده استفاده می‌شود و یا از کلاس‌هایی استفاده می‌شود که قبلا نوشته شده‌اند و به گونه‌ای باشد که طراحان نرم افزار اجازه تغییر در این کلاس‌ها را نداشته باشند، استفاده می‌شود.
الگوی  Adapter انواع مختلفی دارد که فهرست آنها به شرح ذیل می‌باشد:
  1. Class Adapter
  2. Object Adapter
  3. Two way Adapter
  4. Pluggable Adapter
بسیاری از مثال‌های الگوی Adapter درگیر ورودی و خروجی هستند زیرا این دامنه‌ای است که همیشه تغییر می‌کند. برای مثال برنامه‌هایی که در دهه 80 میلادی نوشته شده‌اند دارای UI بسیار ضعیف تری نسبت به برنامه‌های نوشته شده در هزاره سوم میلادی هستند. حال اگر دوباره نویسی همان برنامه‌های قبلی به صرفه نباشد و بخواهیم این برنامه‌ها با سخت افزارهای جدید همخوانی و سازگاری داشته باشند باید برنامه‌ای طراحی کنیم که بین این دو برنامه یعنی برنامه قدیمی و راه اندازهای سخت افزارهای جدید قرار بگیرد و بین این دو برنامه ارتباط برقرار کند. به برنامه‌ای که بین این دو برنامه قرار می گیرد Adapter گویند. حال شاید به نظر برسد که استفاده از Adapter اصلاً نیاز نباشد و می توان واسط یکی از کلاس‌ها را تغییر داد تا بتواند کار کند، این کار زمانی ممکن است که بتوان به کد کلاس‌ها دسترسی داشت و تغییر کلاس‌ها باعث به وجود آمدن مشکل در برنامه نباشد و پیچیدگی برنامه را افزایش ندهد که در اکثر مواقع این عمل به صرفه نیست.
ساختار این الگو به این شکل است:
همانطور که در شکل دیده می‌شود کلاس Adapter از اینترفیس ITarget مشتق شده است و در یکی از متدهایی که در این کلاس وجود دارد (Request) متد مورد نظر را از کلاس Adaptee فراخوانی می‌کند. کلاس Adapter متدهای Adaptee را با متدها و خصوصیات Target وفق می دهد. به طور کلی اینترفیس ITarget همان اینترفیسی است که کاربر آن را پیاده سازی می‌کند و کلاس Adaptee همان کلاسی است که باید با برنامه وفق داده شود. کاربران برای استفاده فقط از کلاس Adapter نمونه سازی می‌کنند و نیازی به درگیری با ارتباط Target و Adaptee نخواهند بود.
کد این الگو به شرح زیر است.
public class Adaptee {
public double specificRequest(double a, double b) {
return a / b;
}
}
public interface ITarget {
String request(int a);
}
public class Adapter extends Adaptee implements ITarget {
public String request(int a) {
return "the result is" + (int) Math.round(specificRequest(a, 5));
}
}

Adapter دوطرفه
ساده ترین شکل الگوی Adapter شکل یک طرفه آن است که یک کلاس یا اینترفیس Target بوده و کلاس دیگر نقش Adaptee را داشت که تا این قسمت شرح داده شد. حال فرض کنید که می‌خواهیم هر دو طرف هم نقش Adaptee و هم نقش Target را داشته باشند. به گونه‌ای که از کلاس Adapter بتوان همه به شکلی استفاده کرد که متدهای هر دو طرف را داشته باشند. در این صورت کلاس Adapter دارای متدها و خصوصیات هر دو کلاس می‌باشد. یک Adapter دو طرفه می‌تواند به جای هر دو کلاس Target و Adaptee مورد استفاده قرار بگیرد. برای این کار در زبان‌هایی مانند ++C که وراثت از چندین کلاس را پشتیبانی می‌کنند کار آسانی است. به این شکل که کلاس Adapter از دو کلاس دیگر ارث بری داشته باشد، همانند ساختار زیر:
اما در بسیاری از زبان های برنامه نویسی رایج مانند #C و Java ارث بری از چندکلاس پشتیبانی نمی‌شود. بنابراین، این راه حل در این زبان‌ها پاسخگو نیست. برای این که در این زبان‌ها از Adapter دو طرفه استفاده کنیم به شکل زیر عمل می کنیم.
public class Adaptee {
public double specificRequest(double a, double b) {
return a / b;
}
}

public interface ITarget {
String request(int a);
}

public class Adapter extends Adaptee implements ITarget {
public String request(int a) {
return "the result is, " + (int) Math.round(specificRequest(a, 5));
}
}

public class App {
public static void main(String[] args) {
Adapter adapter = new Adapter();
System.out.println(adapter.request(5));
System.out.println(adapter.specificRequest(5, 5));
}
}
در کد بالا یکی از اینترفیس ها (IAircraft ) که همان Target است را در کلاس Adapter پیاده سازی می‌کنیم و از کلاس Adaptee ارث بری می‌نماییم. ساختار این عمل شبیه به همان استفاده از الگوی Adapter به شکل یک طرفه آن است ولی در استفاده به این شکل عمل می‌کنیم. همانطور که مشاهده می‌شود می توان از کلاس Adapter هم به عنوان یک نمونه از Target و هم به عنوان یک نمونه از Adaptee استفاده نمود. مشکلی که در زبان هایی مانند C# یا Java وجود دارد این است که باید Target را به عنوان اینترفیس معرفی کرده و در کلاس Adapter آن را پیاده سازی نمود ولی در زبانی مانند C++ چنین محدودیتی وجود ندارد.
تفاوت حوزه های Object و Class

Object: در این روش ناسازگاری با ایجاد یک شی برطرف می‌شود. در این روش کلاس Adapter به جای ارث بری از کلاس Adaptee یک Object از کلاس Adaptee را در خود ایجاد می‌کند. بنابراین شما می‌توانید به چندین کلاس Adaptee توسط کلاس Adapter دسترسی داشته باشید.
Class: در این روش ناسازگاری با وراثت بین کلاس‌ها برطرف می شود. به بیان دیگر کلاس Adapter از ارث بری چندگانه استفاده می‌کند و اینترفیس‌های کلاس‌های Target و Adaptee را با هم سازگار می کند.

مثال پیاده سازی شده با زبان جاوا را می‌توانید از github من دانلود کنید.

نظرات  (۰)

هیچ نظری هنوز ثبت نشده است

ارسال نظر

کاربران بیان میتوانند بدون نیاز به تأیید، نظرات خود را ارسال کنند.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی