#گزارش نهایی آزمایش هشتم
ما الگوی Object Scope (Object Adapter) را به جای Class Scope (Class Adapter) انتخاب کردم. دلایل ما به صورت زیر است:
-
انعطافپذیری: الگوی Object Adapter به adapter ما اجازه میدهد تا با هر پیادهسازی گراف در زمان اجرا کار کند. میتوانیم بین JUNG و JGraphT به سادگی با تغییر نمونهای که از adapter میسازیم جابجا شویم، بدون اینکه نیاز به تغییر کد دیگری باشد.
-
محدودیتهای جاوا: جاوا از وراثت چندگانه پشتیبانی نمیکند، که برای Class Adapter لازم است تا هم از interface GraphAdapter و هم از کلاس concrete گراف (مانند SparseMultigraph) ارثبری کند. استفاده از ترکیب (composition) به جای وراثت تنها گزینه ممکن در جاوا است.
-
کپسولهسازی: Object Adapter کتابخانه گراف زیرین را بهتر کپسوله میکند. کلاسهای traverser فقط از interface GraphAdapter اطلاع دارند، نه از جزئیات پیادهسازی خاص JUNG یا JGraphT.
الگوی Adapter از طریق رویکرد زیر پیادهسازی شد:
-
تعریف Interface: یک interface به نام
GraphAdapter<V,E>ایجاد کردم که عملیاتهای ضروری گراف مورد نیاز traverserها را انتزاعی میکند: افزودن رأسها، افزودن یالها، دریافت همسایهها و دریافت همه رأسها. -
Adapterهای Concrete: دو کلاس adapter concrete پیادهسازی کردم:
JungGraphAdapter: SparseMultigraph از JUNG را wrap میکند و فراخوانیها را به آن واگذار میکندJGraphTGraphAdapter: SimpleGraph از JGraphT را wrap میکند و عملیات را ترجمه میکند
-
تغییر Client: کلاسهای traverser را بهروزرسانی کردم تا به interface GraphAdapter وابسته باشند به جای استفاده مستقیم از کلاسهای JUNG. این جداسازی تضمین میکند که تغییر کتابخانهها فقط نیاز به تغییر نمونهسازی adapter در Main دارد.
تغییر کتابخانه با حداقل تغییر کد انجام شد:
-
نقطه تغییر واحد: فقط کلاس Main نیاز به تغییر داشت - به طور خاص فقط یک خط که در آن adapter را نمونهسازی میکنیم:
\\from: GraphAdapter<Integer, String> graphAdapter = new JungGraphAdapter<>(); \\to: GraphAdapter<Integer, String> graphAdapter = new JGraphTGraphAdapter<>();
-
عدم تغییر الگوریتمها: پیادهسازیهای traverser برای BFS و DFS کاملاً بدون تغییر باقی ماندند، که اثربخشی الگوی Adapter را نشان میدهد.
-
Interface یکسان: همه عملیات گراف (افزودن رأسها، یالها، پیمایش) از دیدگاه client به طور یکسان کار میکنند.
تفاوتهای کلیدی که در طول مهاجرت مواجه شدم:
-
مدیریت یالها:
- JUNG اجازه میدهد یالهای برچسبدار با اشیاء یال صریح داشته باشیم
- SimpleGraph در JGraphT از DefaultEdge استفاده میکند که برچسب را ذخیره نمیکند
- راهحل: برای این پیادهسازی، برچسبهای یال در adapter JGraphT نادیده گرفته میشوند
-
ساخت گراف:
- JUNG:
new SparseMultigraph<>() - JGraphT:
new SimpleGraph<>(DefaultEdge.class)- نیاز به مشخص کردن کلاس یال دارد
- JUNG:
-
بازیابی همسایهها:
- JUNG: متد مستقیم
graph.getNeighbors(vertex) - JGraphT: باید از طریق یالها تکرار کرده و رأس دیگر را به صورت دستی استخراج کنیم
- JUNG: متد مستقیم
-
تفاوتهای API:
- JUNG: از
addVertex()وaddEdge(edge, v1, v2)استفاده میکند - JGraphT: از
addVertex()وaddEdge(v1, v2)استفاده میکند (شیء یال را برمیگرداند)
- JUNG: از
الگوی Strategy در اینجا برای کپسوله کردن الگوریتمهای مختلف پیمایش گراف (BFS و DFS) و قابل تعویض کردن آنها استفاده میشود. این به کد client اجازه میدهد که الگوریتم پیمایش را در زمان اجرا انتخاب کند بدون تغییر ساختار گراف یا منطق اصلی برنامه. این الگو اصل Open/Closed را ترویج میدهد - سیستم برای توسعه باز است (استراتژیهای پیمایش جدید) اما برای تغییر بسته است.
الگوی Strategy از طریق سه جزء پیادهسازی شده است: (۱) interface Traverser قرارداد را برای همه استراتژیهای پیمایش با متد traverse() تعریف میکند، (۲) BfsGraphTraverser و DfsGraphTraverser استراتژیهای concrete هستند که interface را با الگوریتمهای خاص خود پیادهسازی میکنند، و (۳) کلاس Main به عنوان context عمل میکند و انتخاب میکند که کدام استراتژی در زمان اجرا استفاده شود.
همانطور که میبینیم تنها با تغییر یک خط کد که مربوط به adapter می باشد نتیجه یکسان و درست را می گیریم

ترکیب الگوهای Adapter و Strategy یک سیستم بسیار انعطافپذیر و قابل نگهداری ایجاد میکند. الگوی Adapter با موفقیت وابستگی به کتابخانه گراف را جدا کرد و امکان مهاجرت بدون درز از JUNG به JGraphT را با حداقل تغییرات کد فراهم کرد. الگوی Strategy امکان افزودن آسان الگوریتمهای پیمایش جدید را بدون تغییر کد موجود فراهم میکند. این طراحی اصول کلیدی مهندسی نرمافزار از جمله اتصال سست (loose coupling)، انسجام بالا (high cohesion) و پایبندی به اصول SOLID را نشان میدهد.