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

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

جزء من قسم البرمجة كائنية التوجه في رحلة C# على Coddy. الدرس 59 من 70.

يُعد نمط Template Method نمطًا سلوكيًا يحدد الهيكل الأساسي لـ algorithm في base class، مما يتيح للفئات الفرعية إجراء override لخطوات محددة دون تغيير البنية العامة. تتحكم base class في سير العمل، بينما تخصص الفئات المشتقة الأجزاء الفردية.

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

public abstract class DataProcessor
{
    // طريقة القالب - تحدد هيكل الخوارزمية
    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");
}

توفّر كل فئة فرعية implementation الخاصة بها، بينما تفرض base ترتيب operations:

DataProcessor csv = new CsvProcessor();
csv.Process();
// قراءة ملف CSV
// تحليل بيانات CSV
// Saving to default location

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

يكون نمط Template Method مثاليًا عندما تشترك عدة class في بنية algorithm نفسها، لكنها تختلف في خطوات محددة. وهو يعزز إعادة استخدام الشيفرة من خلال وضع المنطق المشترك في base، مع إتاحة المرونة عبر method القابلة للتجاوز.

challenge icon

التحدي

سهل

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

ستنظّم الشيفرة في ثلاثة ملفات:

  • ReportGenerator.cs: أنشئ فئة ReportGenerator من النوع abstract في مساحة الأسماء Reporting. تحدد هذه الفئة الأساسية الهيكل العام لـ algorithm إنشاء التقارير من خلال template method تُسمى Generate(). يجب أن تستدعي الطريقة ثلاث خطوات بالترتيب: GatherData() وFormatReport() وOutputReport(). اجعل GatherData() وFormatReport() من النوع abstract (إذ سينفّذ كل نوع من التقارير هاتين الطريقتين بشكل مختلف)، بينما يجب أن تكون OutputReport() طريقة virtual ذات implementation افتراضي يطبع 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، وتتجاوز 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

لاحظ كيف يتبع كلا التقريرين البنية نفسها تمامًا لـ algorithm (الجمع والتنسيق والإخراج)، لكن يتم تخصيص implementation كل خطوة. يستخدم SalesReport سلوك الإخراج الافتراضي، بينما يتجاوزه InventoryReport - مما يوضح كيف يتيح لك نمط 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اختبر نفسك

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

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم C# عبر الإنترنت