در این آموزش از سری آموزش الگوهای طراحی نرمافزار، قصد داریم به الگوی طراحی Bridge بپردازیم. الگوی طراحی Bridge یک الگوی طراحی ساختاری است که به شما این امکان را میدهد تا یک کلاس بزرگ یا مجموعه ای از کلاسهای نزدیک را به دو سلسله مراتب جداگانه تقسیم کنید – Abstraction و Implementation- که می توانند مستقل از یکدیگر توسعه یابد.
مشکل
فرض کنید که شما یک کلاس شکل هندسی با یک جفت زیر کلاس دارید: دایره و مربع. شما می خواهید این سلسله مراتب کلاس را برای تلفیق رنگ ها گسترش دهید ، بنابراین قصد دارید زیر کلاس های شکل قرمز و آبی ایجاد کنید. با این حال، از آنجا که شما قبلاً دو زیر کلاس دارید، باید چهار ترکیب کلاس مانند BlueCircle و RedSquare ایجاد کنید.
افزودن انواع و قسمهای جدید شکل به سلسله مراتب آن را به صورت نمایی رشد می دهد. به عنوان مثال، برای افزودن یک شکل مثلث ، باید دو زیر کلاس را معرفی کنید، یکی برای هر رنگ. و پس از آن، اضافه کردن یک رنگ جدید به ایجاد سه زیر کلاس نیاز دارد، یکی برای هر نوع شکل. هر چه بیشتر پیش برویم، بدتر می شود.
راهحل
این مشکل به وجود می آید زیرا ما در تلاش هستیم کلاسهای شکل را در دو بعد مستقل گسترش دهیم: به فرم و رنگ. این یک مسئله بسیار متداول با ارث طبقاتی است.
الگوی طراحی Bridge سعی دارد با جابجایی از وراثت به ترکیب شی ، این مشکل را حل کند. این بدان معنی است که شما یکی از ابعاد را در یک سلسله مراتب کلاس جداگانه استخراج می کنید ، به این ترتیب که کلاس های اصلی به جای اینکه همه حالت و رفتارهای خود را در یک طبقه داشته باشند ، مرجع یک سلسله مراتب جدید هستند.
به دنبال این روش ، می توانیم کد مربوط به رنگ را با دو زیر کلاس: قرمز و آبی در کلاس خود استخراج کنیم. کلاس Shape سپس یک قسمت مرجع با اشاره به یکی از اشیاء رنگی دریافت می کند. اکنون شکل می تواند هر کار مرتبط با رنگ را به شیء رنگی مرتبط منتسب کند. این مرجع به عنوان پلی بین طبقات شکل و رنگ عمل خواهد کرد. از این پس ، اضافه کردن رنگ های جدید نیازی به تغییر سلسله مراتب شکل و بالعکس ندارد.
انتزاع و اجرای
کتاب GoF اصطلاحات Abstraction و Implementtion را به عنوان بخشی از تعریف Bridge معرفی می کند. به نظر من، این اصطلاحات بیش از حد آکادمیک به نظر می رسند و باعث میشوند این الگو پیچیده تر از آنچه واقعاً هست، به نظر برسد. با خواندن مثال ساده با شکل ها و رنگ ها، اجازه دهید معنای کلمات ترسناک کتاب GoF را رمزگشایی کنیم.انتزاع (همچنین به عنوان رابط نیز خوانده می شود) یک لایه کنترل سطح بالا برای برخی از موجودات است. این لایه قرار نیست به تنهایی کار واقعی انجام دهد. این لایه باید کار را به لایه پیاده سازی (همچنین به نام platform) واگذار کند.
توجه داشته باشید که ما در مورد رابط ها یا کلاسهای انتزاعی در زبان برنامه نویسی شما صحبت نمی کنیم. اینها یکسان نیستند. هنگام صحبت در مورد برنامه های واقعی، انتزاع(Abstraction) را می توان با یک رابط کاربری گرافیکی (GUI) نشان داد و پیادهسازی(Implementation) آن می تواند کد سیستم عامل اصلی (API) باشد که لایه GUI در پاسخ به تعامل کاربر آنها را فراخوانی کرده است. به طور کلی، شما می توانید چنین برنامه ای را در دو جهت مستقل گسترش دهید:
- چندین رابط کاربری گرافیکی مختلف (برای مثال ، مناسب برای مشتریان معمولی یا سرپرستان) داشته باشید.
- چندین API مختلف را پشتیبانی کنید (برای مثال ، برای اینکه بتوانید برنامه را تحت ویندوز ، لینوکس و MacOS راه اندازی کنید).
در یک سناریو که نمایانگر بدترین حالت است، این برنامه ممکن است مانند یک کاسه اسپاگتی غول پیکر باشد، جایی که صدها شرط، انواع مختلف رابط کاربری گرافیکی را با API های مختلف در سراسر کد به یکدیگر وصل می کنند.
شما می توانید با استخراج کد مربوط به ترکیب های خاص رابط-پلتفرم در کلاس های جداگانه ، نظم و ترتیب را به این آشوب وارد کنید.
با این حال ، به زودی خواهید فهمید که تعداد زیادی از این کلاس ها وجود دارد. سلسله مراتب کلاس بصورت نمایی رشد خواهد کرد زیرا اضافه کردن یک رابط کاربری گرافیکی جدید یا پشتیبانی از API متفاوت مستلزم ایجاد کلاس های بیشتر و بیشتر است.
بیایید سعی کنیم این مسئله را با الگوی Bridge حل کنیم. این نشان می دهد که ما کلاس ها را به دو سلسله مراتب تقسیم می کنیم:ا
نتزاع: لایه GUI برنامه.
پیاده سازی: API های سیستم عامل.
شیء انتزاع ظاهر برنامه را کنترل می کند ، کار واقعی را به شیء پیوند پیاده شده واگذار می کند. پیاده سازی های مختلف تا زمانی که از یک رابط مشترک پیروی کنند قابل تعویض هستند و همین امکان را می دهد که رابط کاربری گرافیکی مشابه را تحت ویندوز و لینوکس کار کند.
در نتیجه ، شما می توانید کلاس های GUI را بدون دست زدن به کلاس های مربوط به API تغییر دهید. علاوه بر این ، اضافه کردن پشتیبانی از سیستم عامل دیگر فقط به ایجاد یک زیر کلاس در سلسله مراتب اجرای نیاز دارد.
ساختار
به دیاگرام زیر توجه کنید:
۱- Abstraction منطق کنترل سطح بالایی را ارائه می دهد. برای انجام کارهای سطح پایین، به Implementation هدف متکی است.
۲- Implementation رابط رایج را برای کلیه concrete implementation ها اعلام می کند. abstraction فقط از طریق روشهایی که در اینجا اعلام شده است می تواند با یک implementation ارتباط برقرار کند.abstraction ممکن است روشهای مشابه implementation را لیست کند ، اما معمولاً abstraction برخی رفتارهای پیچیده را نشان می دهد که به طیف گسترده ای از اقدامات بدوی اعلان شده توسط implementation متکی هستند.
۳- هر Concrete Implementation حاوی کد مخصوص به یک پلتفرم خاص است.
۴- Refined Abstractionsها انواع مختلفی از منطق کنترل را ارائه می دهند. آنها نیز مانند والدینشان از طریق رابط اجرای کلی با implementationهای مختلفی کار می کنند.
۵- معمولاً Client فقط علاقمند به کار با abstraction است. با این حال ، این کار مشتری است که بتواند شیء abstraction را با یکی از اشیاء implementation پیوند دهد.
شبه برنامه
این مثال نشان می دهد که چگونه الگوی Bridge می تواند به تقسیم کد یکپارچه برنامه ای که مدیریت دستگاه ها و کنترل از راه دور آنها را انجام میدهد، کمک کند. کلاس های Device به عنوان implementation عمل می کنند ، در حالی که Remotes بعنوان abstraction عمل می کند.
کلاس کنترل از راه دور پایه یک فیلد مرجع را اعلام می کند که آن را با یک وسیله دستگاه پیوند می دهد. همه از راه دور با دستگاه ها از طریق رابط دستگاه کلی کار می کنند ، که به همان پشتیبانی از راه دور چندین نوع دستگاه اجازه می دهد.می توانید کلاسهای کنترل از راه دور را بطور مستقل از کلاس های دستگاه توسعه دهید. تمام آنچه لازم است ایجاد یک زیر کلاس جدید از راه دور است. به عنوان مثال ، یک کنترل از راه دور اساسی فقط ممکن است دارای دو دکمه باشد ، اما می توانید آن را با ویژگی های اضافی مانند باتری اضافی یا صفحه لمسی گسترش دهید.
در این آموزش سعی کردیم تا مفهوم الگوی طراحی Bridge را بیان کنیم و بدانیم که این الگو چه چالشی را برطرف خواهد کرد. برای پیادهسازی عملی این الگو، بسته به زبان برنامهنویسی مورد نظر، نمونه کدهایی وجود دارد که اکنون قادر به درک آنها هستید.
موفق و پیروز باشید.