در نوشته قبلی به شرح مختصری از الگوهای طراحی نرم افزار پرداختیم و به بررسی نقش الگو ها در توسعه پرداخیتیم. در این قسمت یک الگوی دیگر را با هم بررسی خواهیم کرد و این بار از دسته الگو های Structural.
این درسته از الگوها زمانی برای ما کاربرد دارند که بخواهیم دسته ای از کلاس ها و یا اشیا را با یکدیگر ترکیب کنیم تا یک ساختار بزگتر و پیچیده تر دست پیدا کنیم و به یک کارکرد جدید برسیم یا اینکه یکی از قابلیت های موجود را حذف کنیم. الگوهای موجود در این گروه عبارتند از
• Decorator
• Proxy
• Bridge
• Composite
• Flyweight
• Adapter
• Façade
بعضی مواردی که این الگوها به ما کمک میکنند عبارتند از:
•اضافه یا کم کردن عملکرد یک کلاس
• کنترل دسترسی به یک شی
•کاهش سربار استفاده از اشیا بسیار کوچک که با تعداد زیادی از آنها سر و کار داریم.
•ایجاد یک شی بزرگ در زمان درخواست.
حالا که از نقش این گروه با خبر شدیم به سراغ الگوی مورد نظر برای امروز میرویم.
الگوی Bridge:
به کمک این الگو میتوان تعریف کلاس را از پیاده سازی آن جدا کرد. یکی از کاربردهای این الگو هنگامی است که نیاز به تغییر ورژن داشته باشیم که در آن قسمتی از برنامه قدیمی تغییر کرده اما میخواهیم برنامه قدیمی بدون مشکل کار کند. و در واقع برنامه با توجه به نسخه خود از پیاده سازی قدیمی یا جدید استفاده میکند.
برای روشن تر شودن موضوع مثالی می آوریم. همه با دستگاه های برقی و الکتریکی کم و بیش سر و کار داریم. از زمان های بسیار دور، برای استفاده از وسایل آنها را به کمک دکمه روشن/خاموش ابتدا روشن میکردیم و بعد از پایان کار آنها را خاموش میکردیم. اما در گذشته این کار به کمک کلید های الکترو مکانیکی انجام میشد و امروزه به کمک کلید های الکترونیکی. این تغییر تکنولوژی از الکترومکانیکی به الکترونیکی سرعت، امنیت و سبکی را برای ما به همراه داشت ولی برای استفاده از این امکانات ما نیاز به یادگیری دانش جدید نداشتیم و کماکان با همان دکمه روشن/خاموش با دستگاه کار میکنیم. و این یعنی که تعریف دکمه روشن/خاموش که ما میبینیم از پیاده سازی آن که ما نمیبینیم کاملا جدا شده است.
پیاده سازی:
یکی از راه های متداول برای جدا کردن تعریف کلاس از پیاده سازی آن استفاده از ارث بری است. اما همانطور که میدانید در ارث بری رابطه تنگاتنگی بین والد و فرزند وجود دارد و برای تغییر هر یک نیاز به تغییر دیگیری است. پس این راه حل مشکل ما نیست. ما باید راه حلی داشته باشیم که این دو کاملا از هم جدا شوند و کاربر دچار سردرگمی نشود.
به مثال زیر دقت کنید. اگر ما Parent را در اختیار کاربر قرار دهیم و بعد از مدتی بخواهیم قابلیتی به کلاسهای ارث بری شده اضافه کنیم، برنامه مقصد ما دیگر به درستی کار نخواهد کرد زیرا با تغییر Parent قسمتی که کاربر با آن کار میکرد نیز تغییر میکند.
همین دیگه! تموم شد.
این درسته از الگوها زمانی برای ما کاربرد دارند که بخواهیم دسته ای از کلاس ها و یا اشیا را با یکدیگر ترکیب کنیم تا یک ساختار بزگتر و پیچیده تر دست پیدا کنیم و به یک کارکرد جدید برسیم یا اینکه یکی از قابلیت های موجود را حذف کنیم. الگوهای موجود در این گروه عبارتند از
• Decorator
• Proxy
• Bridge
• Composite
• Flyweight
• Adapter
• Façade
بعضی مواردی که این الگوها به ما کمک میکنند عبارتند از:
•اضافه یا کم کردن عملکرد یک کلاس
• کنترل دسترسی به یک شی
•کاهش سربار استفاده از اشیا بسیار کوچک که با تعداد زیادی از آنها سر و کار داریم.
•ایجاد یک شی بزرگ در زمان درخواست.
حالا که از نقش این گروه با خبر شدیم به سراغ الگوی مورد نظر برای امروز میرویم.
الگوی Bridge:
به کمک این الگو میتوان تعریف کلاس را از پیاده سازی آن جدا کرد. یکی از کاربردهای این الگو هنگامی است که نیاز به تغییر ورژن داشته باشیم که در آن قسمتی از برنامه قدیمی تغییر کرده اما میخواهیم برنامه قدیمی بدون مشکل کار کند. و در واقع برنامه با توجه به نسخه خود از پیاده سازی قدیمی یا جدید استفاده میکند.
برای روشن تر شودن موضوع مثالی می آوریم. همه با دستگاه های برقی و الکتریکی کم و بیش سر و کار داریم. از زمان های بسیار دور، برای استفاده از وسایل آنها را به کمک دکمه روشن/خاموش ابتدا روشن میکردیم و بعد از پایان کار آنها را خاموش میکردیم. اما در گذشته این کار به کمک کلید های الکترو مکانیکی انجام میشد و امروزه به کمک کلید های الکترونیکی. این تغییر تکنولوژی از الکترومکانیکی به الکترونیکی سرعت، امنیت و سبکی را برای ما به همراه داشت ولی برای استفاده از این امکانات ما نیاز به یادگیری دانش جدید نداشتیم و کماکان با همان دکمه روشن/خاموش با دستگاه کار میکنیم. و این یعنی که تعریف دکمه روشن/خاموش که ما میبینیم از پیاده سازی آن که ما نمیبینیم کاملا جدا شده است.
پیاده سازی:
یکی از راه های متداول برای جدا کردن تعریف کلاس از پیاده سازی آن استفاده از ارث بری است. اما همانطور که میدانید در ارث بری رابطه تنگاتنگی بین والد و فرزند وجود دارد و برای تغییر هر یک نیاز به تغییر دیگیری است. پس این راه حل مشکل ما نیست. ما باید راه حلی داشته باشیم که این دو کاملا از هم جدا شوند و کاربر دچار سردرگمی نشود.
به مثال زیر دقت کنید. اگر ما Parent را در اختیار کاربر قرار دهیم و بعد از مدتی بخواهیم قابلیتی به کلاسهای ارث بری شده اضافه کنیم، برنامه مقصد ما دیگر به درستی کار نخواهد کرد زیرا با تغییر Parent قسمتی که کاربر با آن کار میکرد نیز تغییر میکند.
public interface Parent
{
string GetClassName();
}
public class Child1 : Parent
{
public string GetClassName()
{
return "Class1";
}
}
public class Child2 : Parent
{
public string GetClassName()
{
return "Class1";
}
}
حال به مثال زیر دقت کنید که جداسازی را به کمک Bridge انجام میدهیم:{
string GetClassName();
}
public class Child1 : Parent
{
public string GetClassName()
{
return "Class1";
}
}
public class Child2 : Parent
{
public string GetClassName()
{
return "Class1";
}
}
public class Abstraction
{
IBridge bridg;
public Abstraction(IBridge implementation)
{
bridg = implementation;
}
public string GetName()
{
return bridg.GetClassName();
}
}
public interface IBridge
{
string GetClassName();
}
public class Implementation1:IBridge
{
public string GetClassName()
{
return "Implementation1";
}
}
public class Implementation2 : IBridge
{
public string GetClassName()
{
return "Implementation2";
}
}
در کد بالا مشاهده میکنید که قسمت Abstract که در دست کاربر است کاملا از قسمتی که نیاز به تغییر و تعیریف مجدد دارد جدا گشته است و هر تغییری که در قسمت Bridge بدهیم روی قسمت کاربر تاثیری نمیگذارد.{
IBridge bridg;
public Abstraction(IBridge implementation)
{
bridg = implementation;
}
public string GetName()
{
return bridg.GetClassName();
}
}
public interface IBridge
{
string GetClassName();
}
public class Implementation1:IBridge
{
public string GetClassName()
{
return "Implementation1";
}
}
public class Implementation2 : IBridge
{
public string GetClassName()
{
return "Implementation2";
}
}
همین دیگه! تموم شد.
3 نظرات:
فکر میکنم به الگوی Factory که توی یک پست دیگه توضیح دادید شباهت داشته باشه ...
سلام حسین جان
از اینکه مطالب رو دنبال میکنی ازت ممنونم.
شاید در نگاه اول این طور به نظر بیاد، اما این دو تا الگو توی دوتا دسته بندی کاملا جدا قرار میگیرند.
الگوی Factory به ما کمک میکنه که هنگام ساخته شدن یک شی تصمیم گیری انجام بدیم و برنامه هست که تصمیم میگیره با توجه به شرایط چه نمونه ای از چه کلاسی ساخته بشود، اما الگوی bridge در ساختار بندی کلاس دخالت دارد.
به نظرم یه کمی بیشتر با DI برادر هستن.
موفق باشید
مرسی از این وقت میذارید و دانسته هاتون رو به اشتراک میذارید.
مرسی از راهنماییتون
ارسال یک نظر