مشخصات مقاله
-
1922
-
0.0
-
7348
-
0
-
0
Design Patterns-الگوی Bridge
Bridge
در صورتی که مقالات قبلی را مطالعه نکرده اید، از طریق لینک های زیر قابل دسترس هستند:
- Design Patterns
- Singleton Pattern
- Simple Factory Pattern
- Abstract Factory Pattern
- Factory Method Pattern
- Prototype Pattern
- Builder Pattern
- Façade Pattern
- Adapter Pattern
- Decorator Pattern
در این مقاله قصد داریم راجع به یکی دیگر از الگوهای طراحی ساختاری به نام Bridge کار کنیم. گروه GOF اینطور الگوی Bridge را تعریف می کنند:"این الگو abstraction را از پیاده سازی جدا می کند. بنابراین می توانند مستقل از هم با شند".
بسیار خوب، بیائید ببینیم کاربرد این الگو در کجاست. در صورتی که بیش از یک متد abstract داشته باشیم و روش های مختلفی برای پیاده سازی آنها وجود داشته باشد، آنگاه باید برای هر نسخه abstract یک کلاس جدید ایجاد کرد و در آخر ممکن است با کلاس های زیادی مواجه شویم. الگوی Bridge
برای حل این مشکل یک راه حل ارائه کرده است. در این الگو یک اینترفیس به عنوان یک پل (Bridge) بین کلاس های Abstract و معمولی، معرفی می شود.
در ادامه می توانید UML مربوط به الگوی Bridge را مشاهده کنید.
الگوی Bridge از چهار عنصر کلیدی تشکیل شده است:
- Abstraction: کلاسی که با client سرو کار دارد. این کلاس ارجاع یک شی از نوع Implementor را نگهداری می کند.
- RefinedAbstraction: کلاس Abstraction را توسعه می دهد تا چندین نسخه از متدهای abstract داشته باشد.
- Implementor یا Bridge: این اینترفیس مانند یک پل بین کلاس های abstract و کلاس های معمولی عمل میکند.
- ConcreteImplementor: این کلاس اینترفیس Implementor را پیاده سازی میکند.
چگونگی عملکرد الگوی Bridge
با یک مثال ساده شروع می کنیم. این سناریو را در نظر بگیرید که چند نوع ایمیل برای ارسال داشته باشیم و در هرلحظه می توانیم به چند روش آنها را ارسال کنیم. می خواهید این اجازه را به client بدهید که خودش یک ایمیل یا یک روش خاص را برای ارسال انتخاب کند.
برای چنین موردی از الگوی Bridge استفاده می کنیم. چرا که در این صورت می توانیم چندین منبع مختلف (یا متدهای abstract) و چندین هدف (پیاده سازی های معمولی) داشته باشیم.
با پیاده سازی اینترفیس Implementor شروع میکنیم.
///
/// The Bridge or Implementor interface
///
public interface IEmailSender
{
void SendEmail(string subject, string body);
} سپس پیاده سازی کلاس abstract ای که اشیاء و متدهای Bussiness را تعیین میکند.
///
/// The Abstraction class
///
public abstract class Email
{
public IEmailSender MessageSender
{
get;
set;
}
public string Subject {
get;
set;
}
public string Body {
get;
set;
}
public abstract void Send();
} همانطور که مشاهده می کنید کلاس Email یک ارجاع از IEmailSender در خود دارد تا بتواند در زمان اجرا، از طریق آن Implementor مناسب را فراخوانی کند.
حالا باید کلاس های RefinedAbstraction را بسازیم و به این ترتیب چندین نسخه از متدهای abstract را پشتیبانی کنیم. بنابراین دو نوع Abstraction خواهیم داشت: SystemEmail و UserEmail.
///
/// The RefinedAbstraction class
///
public class SystemEmail : Email
{
public override void Send()
{
string emailSubject = string.Format("Subject: {0} from System", Subject);
string emailBody = string.Format("Email Body:\n{0}", Body);
MessageSender.SendEmail(emailSubject, emailBody);
}
}
///
/// The RefinedAbstraction class
///
public class UserEmail : Email
{
publicoverridevoid Send()
{
stringemailSubject = string.Format("Subject: {0} from User", Subject);
stringemailBody = string.Format("Email Body:\n{0}", Body);
MessageSender.SendEmail(emailSubject, emailBody);
}
} در ادامه پیاده سازی کلاس های معمولی را مشاهده می کنید. این کلاس ها از ایده چند هدف پشتیبانی میکنند:
///
/// The ConcreteImplementor class
///
public class WebServiceEmailSender: IEmailSender
{
public void SendEmail(string subject, string body)
{
Console.WriteLine("Sending Email using WebService:\n{0}\n{1}\n", subject, body);
}
}
///
/// The ConcreteImplementor class
///
public class WCFEmailSender: IEmailSender
{
public void SendEmail(string subject, string body)
{
Console.WriteLine("Sending Email using WCF:\n{0}\n{1}\n", subject, body);
}
}
///
/// The ConcreteImplementor class
///
public class WebAPIEmailSender: IEmailSender
{
public void SendEmail(string subject, string body)
{
Console.WriteLine("Sending Email using Web API:\n{0}\n{1}\n", subject, body);
}
}همانطور که در قطعه کد فوق مشاهده کردید، سه نوع پیاده سازی برای client مهیا شده است که می تواند هر کدام از آنها را انتخاب کند.
حال ببینیم که Client چطور از این الگو در عمل استفاده می کند:
Console.Title = "Bridge pattern demo"; IEmailSenderwebService = newWebServiceEmailSender(); IEmailSenderwcf = newWCFEmailSender(); IEmailSenderwebApi = newWebAPIEmailSender(); //System Email Emailemail = newSystemEmail(); email.Subject = "Test Message"; email.Body = "Hi there, This is a Test Message from System"; email.MessageSender = webService; email.Send(); email.MessageSender = wcf; email.Send(); email.MessageSender = webApi; email.Send(); //User Email email = newUserEmail(); email.Subject = "Test Message"; email.Body = "Hi there, This is a Test Message from Prakash"; email.MessageSender = webApi; email.Send();
خروجی:
همانطور که مشاهده کردید، با استفاده از الگوی Bridge، client به راحتی می تواند متد abstract مورد نظر خود (بین SystemEmail و UserEmail) و همچنین پیاده سازی خاصی (بین WebService، WCF و یا WebAPI) انتخاب کند.
ممکن است الگوی های Bridge و Adapter کمی شما را دچار سردرگمی کنند. توجه داشته باشید که از الگوی Adapter برای کار کردن با دو اینترفیس ناهمسازگار استفاده می شود که قابلیت های یکسانی دارند، اما نام متدها و یا نوع بازگشتی آنها متفاوت هستند. از طرفی، از الگوی Bridge زمانی استفاده می شود که client نیاز داشته باشد بین متدهای abstract و پیاده سازی های مختلف یکی را انتخاب کند و هم متدهای abstract و هم پیاده سازی آنها به صورت مستقل از هم بروزرسانی می شوند.