المعلوماتية > برمجيات
أنماط التصميم Design Patterns؛ الأنماط البنيوية (Structural Pattern)
تهتم الأنماط البنيوية في تركيب كُلٍّ من الصفوف (classes) والأنماط المُجرّدة (interfaces) والأغراض (objects) إلى بنى أكبر وذات فائدة. يمكن استخدام هذه الأنماط إما عن طريق الوراثة (Inheritance) وإما عن طريق التركيب (composition)، ولذلك؛ تُصنّف هذه الأنماط فرعيًّا إلى صنفين: أنماط الصفوف (class patterns)، وأنماط الأغراض (object patterns).
تستخدم أنماط الصفوف البنيوية (class structural patterns) الوراثة لإنشاء صفوف جديدة ذات فائدة أكبر، ويُستخدَم فيها العلاقة IS-A (علاقة من نوع؛ فمثلًا الطالب هو من نوع الإنسان Student is a Person). أما في أنماط الأغراض البنيوية (object structural pattern) فهي على عكس سابقتها؛ إذ تستخدم العلاقة HAS-A فيما بينها (أي يتكون من؛ فمثلًا السيارة تتكون من محرك ومقاعد … إلخ، Car has an engine, seats … etc) (1).
سنتحدث في هذا المقال عن ثلاثة أنماط تنتمي للأنماط البنيوية، وهي: نمط التَّكييف (adapter pattern)، ونمط الواجهة الزائفة (façade pattern)، ونمط التفويض أو الوكيل (proxy pattern).
نمط التَّكييف Adapter pattern
يُستخدَم في تغيير واجهة الصنف بدون تغيير العمليات الأساسية الخاصة به.أحد الأمثلة لتوضيح هذا النمط هو مثال قارئة الذواكر؛ فهي تعمل وسيطًا بين بطاقة الذاكرة والحاسوب المحمول؛ إذ يُوفّر الحاسوب المحمول واجهة مُوحّدة (المكان الذي تضع فيه قارئة الذواكر)، وعلى اختلاف أنواع بطاقات الذاكرة غير المتوافقة مع واجهة الحاسب المحمول الخاص بك؛ فإنك تحتاج طريقةً لتكييف بطاقة الذاكرة مع الحاسب المحمول، وهذه الطريقة هي قارئة الذواكر.
متى نستخدم هذا النمط؟
- عندما تحتاج استخدام أصناف جاهزة (بطاقات الذاكرة)، ولكنّ واجهته البرمجية (interface) لا تتطابق مع تلك التي لديك (حاسبك المحمول).
- عندما تحتاج إنشاءَ صنف يتضمن أصنافًا أخرى لا تحتوي على واجهات برمجية متوافقة (2).
نمط الواجهة الزائفة Facade pattern
إنّ تقسيم النظام إلى عدد من الأنظمة الفرعية يساعد على تخفيف تعقيده، وهدفٌ أساسي من أهداف أنماط التصميم هو تقليل الاعتماديات بين هذه الأنظمة.إحدى الطرائق لتحقيق هذا الهدف هي التعريف بواجهة زائفة facade object؛ إذ يزوّد من يحتاجه بواجهة برمجية مُبسّطة عن النظام الفرعي. إضافةً إلى ذلك، يسمح لك هذا النمط بإجراء تعديلات على النظام الفرعي دون التأثير في مستخدمي هذا النظام.
كمثال من الحياة؛ يمكنك تخيل أزرار التحكم الخاصة بالمايكرويف (وهي تُعبّر عن الواجهة التي تتعامل معها)، فهي تحتوي على أزرار تُبسّط تعاملك مع هذه الآلة عوضًا عن حفظك الإعدادات الخاصة بكل نوع من الأطعمة وضبطها يدويًّا، إذًا هي واجهة مُبسّطة توفر أزرارًا يتكرر استخدامها وتُبسّط تعاملك معه، فهناك زر خاص بتسخين اللحوم، وزر آخر لتسخين الأطعمة المجمدة، وهكذا. وبالطبع في حال أردت تسخين شيء ذي تعقيد أكبر؛ فلا يزال لديك إمكانية الضبط اليدوي (1، 2).
متى نستخدم هذا النمط؟
- عندما تريد تزويد واجهة برمجية بسيطة لنظام فرعي مُعقد (في مثالنا الواجهة البرمجية البسيطة هي الأزرار الخاصة بأنواع الأطعمة الشائعة).
- عندما يكون هناك العديد من الاعتماديات بين مُستخدمي النظام الفرعي المُعقّد والتنجيز الخاص بتجريده. إنّ تعريف واجهة مزيفة لهذا النظام الفرعي يفصل هذا النظام عن مُستخدميه، ومن ثم يصبح النظام الفرعي أقلَّ اعتمادية وأكثر قابلية للنقل.
- عندما تريد تحويل النظام الفرعي إلى طبقات، بحيث تُعرّف الواجهة المزيفة المدخل الخاص بكل طبقة من نظامك الفرعي، وعن طريق حصر التواصل بين هذه الطرقات بالواجهات المزيفة الخاصة بكل طبقة؛ تكون قد بسّطتَ الاعتماديات بينهم (2).
نمط التفويض أو الوكيل Proxy Pattern
يخدم هذا النمط هدفًا مهمًّا في التحكم بالوصول إلى أغراض أخرى؛ خاصةً إذا كان ذاك الغرض لم يُنشَأ بعد، أو إذا كان إنشاء غرض ما مكلف (بسبب عملية حسابية مُعقدة مثلًا)، فعندها يمكن تمثيله باستخدام وكيل proxy، بحيث تستطيع التحكم بالغرض عن طريق إنشائه مباشرة واستعماله عند جاهزيته، أو تأجيل إنشائه إلى حين الحاجة إليه (3).مثالٌ للتوضيح: عندما تفتح صفحة ويب تحتوي على كثيرٍ من الصور والفيديوهات ويبدأ المتصفح مباشرة بتحميلها مع فتح الصفحة؛ عندها سوف يحتاج المتصفح كثيرًا من الوقت ومصادر الشبكة حتى ينتهي من تحميل الصفحة. أما إذا استخدمَ صورةً مُصغّرة (thumbnail) عن الصورة أو الفيديو (وهي تُعبّر عن الوكيل بحالتنا هذه) وأجّل تحميل الصورة أو الفيديو الأساسي إلى حين النقر عليه؛ فستصبح عملية فتح الصفحة أسرع.
متى نستخدم هذا النمط؟
- عندما نحتاج وكيلًا لغرض بعيد (remote proxy)؛ وهو عبارة عن غرض محلي (local object) يُمثل غرضًا بعيدًا (remote object) يوجد في نظام آخر، وباستدعاء أحد دالاته نستدعي الدالة المُماثلة لها في الغرض البعيد.
- عندما نحتاج وكيلًا افتراضيًّا لغرض ذي إنشاء مُعقّد، ويُدعَى هذا الوكيل بالوكيل الافتراضي (virtual proxy).
- عندما نحتاج وكيلًا يُحدد ويتحكم بالوصول إلى الغرض المُراد استخدامه، ويُدعَى هذا الوكيل بوكيل الحماية (protection proxy (2.
هناك أنماط بنيوية أخرى عديدة لم نذكرها، منها: نمط المُرّكب (Composite pattern)، ونمط وزن الذبابة (Flyweight)، ونمط الجسر (Bridge) وغيرها، ولكن تحدثنا عن الأنماط الثلاثة الأكثر استخدامًا.
المصادر:
2- Singleton [Internet]. Cs.unc.edu. [cited 22 November 2020]. Available from: هنا;
3- C. Martin R. Design Principles and Design Patterns [Internet]. Staff.cs.utu.fi. 2000 [cited 19 April 2021]. Available from: هنا;