Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط طريقة القالب

جزء من قسم Object Oriented Programming في رحلة C# على Coddy — الدرس 59 من 70.

إن نمط طريقة القالب (Template Method pattern) هو نمط سلوكي يحدد الهيكل العام لخوارزمية في فئة أساسية، مما يسمح للفئات الفرعية بتجاوز خطوات محددة دون تغيير الهيكل العام. تتحكم الفئة الأساسية في سير العمل، بينما تقوم الفئات المشتقة بتخصيص الأجزاء الفردية.

يستخدم هذا النمط الوراثة والأساليب المجردة. تحتوي الفئة الأساسية على "طريقة قالب" (template method) تستدعي سلسلة من الخطوات، بعضها مجرد ويجب تنفيذها بواسطة الفئات الفرعية:

public abstract class DataProcessor
{
    // Template method - يحدد هيكل الخوارزمية
    public void Process()
    {
        ReadData();
        ProcessData();
        SaveData();
    }
    
    protected abstract void ReadData();
    protected abstract void ProcessData();
    protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}

public class CsvProcessor : DataProcessor
{
    protected override void ReadData() => Console.WriteLine("Reading CSV file");
    protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}

public class JsonProcessor : DataProcessor
{
    protected override void ReadData() => Console.WriteLine("Reading JSON file");
    protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
    protected override void SaveData() => Console.WriteLine("Saving to cloud");
}

توفر كل فئة فرعية تنفيذها الخاص بينما تفرض الفئة الأساسية ترتيب العمليات:

DataProcessor csv = new CsvProcessor();
csv.Process();
// قراءة ملف CSV
// تحليل بيانات CSV
// الحفظ في الموقع الافتراضي

DataProcessor json = new JsonProcessor();
json.Process();
// قراءة ملف JSON
// تحليل بيانات JSON
// الحفظ في السحابة

يعد نمط "طريقة القالب" (Template Method pattern) مثاليًا عندما تشترك فئات متعددة في نفس هيكل الخوارزمية ولكنها تختلف في خطوات محددة. فهو يعزز إعادة استخدام الكود من خلال وضع المنطق المشترك في الفئة الأساسية مع السماح بالمرونة من خلال الدوال القابلة للتجاوز.

challenge icon

التحدي

سهل

لنقم ببناء نظام لإنشاء التقارير باستخدام نمط Template Method. تشترك الأنواع المختلفة من التقارير (مثل تقارير المبيعات وتقارير المخزون) في نفس الهيكل العام - فجميعها بحاجة إلى جمع البيانات، وتنسيقها، وإخراج النتيجة - ولكن كل نوع من التقارير يتعامل مع هذه الخطوات بشكل مختلف.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • ReportGenerator.cs: أنشئ فئة مجردة (abstract class) باسم ReportGenerator داخل مساحة الأسماء Reporting. تحدد هذه الفئة الأساسية الهيكل العظمي لخوارزمية إنشاء التقرير من خلال "طريقة قالب" (template method) تسمى Generate(). يجب أن تستدعي هذه الطريقة ثلاث خطوات بالترتيب: GatherData()، و FormatReport()، و OutputReport(). اجعل GatherData() و FormatReport() مجردتين (ستقوم كل فئة تقرير بتنفيذهما بشكل مختلف)، بينما يجب أن تكون OutputReport() طريقة افتراضية (virtual method) مع تنفيذ افتراضي يطبع Sending to default printer.
  • ConcreteReports.cs: أنشئ فئتين محددتين للتقارير في نفس مساحة الأسماء ترثان من ReportGenerator:
    • SalesReport - تنفذ GatherData() لطباعة Collecting sales data from database و FormatReport() لطباعة Formatting as sales summary
    • InventoryReport - تنفذ GatherData() لطباعة Scanning warehouse inventory، و FormatReport() لطباعة Formatting as inventory list، وتقوم بعمل override لـ OutputReport() لطباعة Sending to warehouse manager
  • Program.cs: اجمع كل شيء معاً عن طريق إنشاء مثيلات للتقارير وتوليدها. تضمن "طريقة القالب" (template method) أن يتبع كل تقرير نفس العملية المكونة من ثلاث خطوات، ولكن السلوك المحدد لكل خطوة يختلف بناءً على نوع التقرير.

ستتلقى مدخلاً واحداً:

  • نوع التقرير: sales أو inventory

أنشئ مولد التقارير المناسب بناءً على المدخلات واستدعِ طريقة Generate() الخاصة به.

على سبيل المثال، إذا كان المدخل هو sales، يجب أن يكون المخرج:

Collecting sales data from database
Formatting as sales summary
Sending to default printer

إذا كان المدخل هو inventory، يجب أن يكون المخرج:

Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse manager

لاحظ كيف يتبع كلا التقريرين نفس هيكل الخوارزمية تماماً (الجمع، التنسيق، الإخراج)، ولكن تنفيذ كل خطوة مخصص. يستخدم SalesReport سلوك الإخراج الافتراضي، بينما يقوم InventoryReport بتجاوزه (override) - مما يوضح كيف يتيح لك نمط Template Method التحكم في الخطوات الإلزامية للتجاوز والخطوات التي يمكن تخصيصها اختيارياً!

جرّب بنفسك

using System;
using Reporting;

class Program
{
    public static void Main(string[] args)
    {
        string reportType = Console.ReadLine();
        
        // TODO: قم بإنشاء منشئ التقارير المناسب بناءً على reportType
        // إذا كان reportType هو "sales"، فقم بإنشاء SalesReport
        // إذا كان reportType هو "inventory"، فقم بإنشاء InventoryReport
        // ثم قم باستدعاء الدالة Generate() في التقرير
        
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming