نمط طريقة القالب
جزء من قسم البرمجة كائنية التوجه في رحلة Dart على Coddy. الدرس 97 من 110.
يحدّد نمط Template Method الهيكل الأساسي لخوارزمية في الفئة الأساسية، مما يتيح للفئات الفرعية تجاوز خطوات محددة دون تغيير البنية العامة. تتحكّم الفئة الأساسية في سير العمل، بينما تخصّص الفئات الفرعية الخطوات الفردية.
يستخدم هذا النمط الوراثة: يعرّف الصنف abstract طريقة قالب تستدعي سلسلة من الخطوات، بعضها abstract (ويجب أن تنفذها الأصناف الفرعية) وبعضها الآخر له تطبيقات افتراضية:
abstract class DataProcessor {
// طريقة القالب - تحدد هيكل الخوارزمية
void process() {
readData();
processData();
saveData();
}
void readData(); // مجردة - يجب على الفئات الفرعية تنفيذها
void processData(); // مجردة - يجب على الفئات الفرعية تنفيذها
void saveData() { // التنفيذ الافتراضي
print('Data saved to database');
}
}
class CsvProcessor extends DataProcessor {
@override
void readData() => print('Reading CSV file');
@override
void processData() => print('Parsing CSV rows');
}
class JsonProcessor extends DataProcessor {
@override
void readData() => print('Reading JSON file');
@override
void processData() => print('Parsing JSON objects');
@override
void saveData() => print('Saved to cloud storage');
}
void main() {
var csv = CsvProcessor();
csv.process();
// قراءة ملف CSV
// تحليل صفوف CSV
// تم حفظ البيانات في قاعدة البيانات
var json = JsonProcessor();
json.process();
// قراءة ملف JSON
// تحليل كائنات JSON
// تم الحفظ في التخزين السحابي
}طريقة process() هي القالب - فهي defines ترتيب العمليات. تنفّذ الفئات الفرعية readData() وprocessData() بطريقة مختلفة، ويمكنها اختياريًا تجاوز saveData(). وتتمثل الفائدة الأساسية في أن بنية algorithm تظل متسقة عبر جميع عمليات implement، مع السماح بالمرونة في الخطوات الفردية.
التحدي
سهللنبنِ نظامًا لتوليد التقارير باستخدام نمط Template Method! ستنشئ إطارًا تتبع فيه أنواع مختلفة من التقارير البنية العامة نفسها، لكن يخصص كل نوع من التقارير خطوات محددة مثل جمع البيانات وتنسيق الناتج.
ستنظم التعليمات البرمجية في ملفين:
report_generator.dart: يحتوي هذا الملف على الفئة الأساسية abstract وتنفيذات التقارير Concrete. أنشئ فئة abstract باسمReportGeneratorمع method قالب تُسمىgenerate()وتحدد سير عمل توليد التقرير بهذا الترتيب:fetchData()، وanalyzeData()، وformatReport()، وdeliver(). يجب أن تكون methodاfetchData()وformatReport()abstract (يتعامل كل نوع من التقارير معهما بشكل differently)، بينما يجب أن تطبعanalyzeData()القيمةAnalyzing data...، وأن تطبعdeliver()القيمةReport delivered via email.بوصفهما تنفيذين Default. ثم أنشئ فئتي تقارير Concrete:SalesReport- تطبعfetchData()الخاصة بهاFetching sales data from database...، وتطبعformatReport()الخاصة بهاFormatting as bar charts and tables.InventoryReport- تطبعfetchData()الخاصة بهاFetching inventory levels from warehouse...، وتطبعformatReport()الخاصة بهاFormatting as inventory list.، كما تتجاوزdeliver()لتطبعReport sent to warehouse manager.
main.dart: استورد file الخاص بمولّد التقارير ووضّح كيف يحافظ نمط Template Method على اتساق بنية algorithm مع السماح بالتخصيص. أنشئ كائنًا منSalesReportواستدعِ methodgenerate()الخاصة به. ثم اطبع سطرًا empty للفصل. أنشئ كائنًا منInventoryReportواستدعِ methodgenerate()الخاصة به أيضًا.
لاحظ كيف يتبع كلا التقريرين العملية نفسها المكوّنة من أربع خطوات، لكن كلًّا منهما يخصص الخطوات المهمة لغرضه المحدد. بل إن InventoryReport يتجاوز method التسليم Default لإرسال التقارير إلى مستلم مختلف!
الناتج المتوقع:
Fetching sales data from database...
Analyzing data...
Formatting as bar charts and tables.
Report delivered via email.
Fetching inventory levels from warehouse...
Analyzing data...
Formatting as inventory list.
Report sent to warehouse manager.جرّب بنفسك
import 'report_generator.dart';
void main() {
// TODO: أنشئ SalesReport واستدعِ method generate() الخاصة به
// TODO: اطبع سطرًا فارغًا للفصل
// TODO: أنشئ InventoryReport واستدعِ method generate() الخاصة به
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP
الملفات الخارجيةالمكتبات والـ Importsمقدمة في الـ OOPالـ Classes مقابل الـ Objectsالكلمة المفتاحية thisالـ Methodsمتغيرات الـ Instanceأساسيات الـ Constructorمراجعة - آلة حاسبة بسيطة4أمان الـ Null
مقدمة في أمان الـ NullNullable مقابل Non-Nullableعاملا الـ ? و !الكلمة المفتاحية Late وأمان الـ Nullالعوامل المدركة للـ Nullأمان الـ Null في الـ Classesمراجعة - نظام ملف تعريف المستخدم7الفئات المجردة والواجهات
الفئات المجردةالدوال المجردةالواجهات في Dartالواجهات الضمنيةالتنفيذ مقابل التوسيعالواجهات المتعددةمراجعة - حاسبة الأشكال10المجموعات والأنماط العامة
نظرة عامة على List و Set و Mapالمجموعات آمنة النوعالفئات العامةالدوال العامةقيود الأنماط العامةIterable و Iteratorملخص - التخزين العام13مفاهيم OOP المتقدمة
التركيب مقابل الوراثة (Composition vs Inheritance)دوال التوسعة (Extension Methods)الأصناف القابلة للاستدعاء (Callable Classes)الأصناف المختومة (Sealed Classes - Dart 3)السجلات (Records - Dart 3)الأنماط والمطابقة (Patterns & Matching - 3.0)التعدادات مع الدوال (Enums with Methods)2المنشئات في Dart
المنشئ الافتراضيالمنشئات المسماةقوائم التهيئةالمنشئات الثابتةالمنشئات المصنعيةالمنشئات الموجهةملخص - بناء الأشكال5التغليف (Encapsulation)
الأعضاء العامة مقابل الخاصةاتفاقية البادئة _الخصوصية على مستوى المكتبةتعمق في Getters و Settersإخفاء المعلوماتمراجعة - سجلات الطلاب8Mixins
مقدمة إلى Mixinsإنشاء Mixinsاستخدام Mixins متعددةالكلمة المفتاحية on في MixinsMixin مقابل الوراثة (Inheritance)Mixin مقابل الواجهة (Interface)مراجعة - نظام الحيوانات (Animal System)3خصائص الـ Class
أعضاء الـ Instance مقابل الـ Staticحقول Final و Constمتغيرات Lateالـ Static Methods والحقولدوال الـ Getters والـ Settersمراجعة - مدير الحساب البنكي6الوراثة
أساسيات الوراثةالكلمة المفتاحية superإعادة تعريف الدوال (Method Overriding)الوسم @overrideالكلمة المفتاحية final Classالدوال البانية والوراثةمراجعة - هيكلية الموظفين9تعدد الأشكال
أساسيات تعدد الأشكالتعدد الأشكال عبر الـ Interfacesالتحقق من النوع أثناء التشغيلالمعاملات is و asالكلمة المفتاحية Covariantملخص - معالج الدفع12البرمجة الكائنية غير المتزامنة (Async OOP)
Futures و async/awaitأساسيات الـ Streamsمتحكمات الـ Streamsالـ Constructors غير المتزامنةالعمليات غير المتزامنة في دوال الكلاسمراجعة - جالب البيانات (Data Fetcher)15أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المستودعتدرّب بنفسك: مترجم Dart عبر الإنترنت