نمط طريقة القالب
جزء من قسم البرمجة كائنية التوجه في رحلة 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 القابلة للتجاوز.
التحدي
سهللنَبْنِ نظامًا لإنشاء التقارير باستخدام نمط 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 summaryInventoryReport- تنفّذ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() على التقرير
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات OOP
الملفات الخارجيةNamespaces والتوجيهاتمقدمة في Classes و Objectsالكلمة المفتاحية 'this'Methods والمعاملاتFields مقابل PropertiesConstructorsObject Initializersمراجعة - آلة حاسبة بسيطة4الوراثة
صيغة الوراثة الأساسية (:)الكلمة المفتاحية 'base'الكلمات المفتاحية Virtual و Overrideالأصناف المختومة (Sealed Classes)الفئة الأساسية 'object'مراجعة - هيكلية الموظفين7ميزات متقدمة
تحميل العوامل (Operator Overloading)المفهرسات (Indexers (this[]))إعادة تعريف ()ToStringدوال التوسعة (Extension Methods)ملخص - Custom List2الخصائص والأعضاء الساكنة (Static Members)
الخصائص المطبقة تلقائيًا (Auto-Implemented Properties)خصائص القراءة فقط والكتابة فقطالحقول والدوال الساكنة (Static)الفئات الساكنة (Static Classes)الأعضاء ذات البنية التعبيرية (Expression-Bodied Members)5تعدد الأشكال والواجهات (Polymorphism & Interfaces)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالواجهة مقابل الفئة المجردة (Abstract Class)الواجهات المتعددةالواجهات الصريحةUpcasting و Downcastingملخص - حاسبة الأشكال8مفاهيم البرمجة كائنية التوجه (OOP) المتقدمة
التركيب بدلاً من الوراثةالـ Generics (الأصناف والدوال)الـ Delegates والأحداثالـ Attributes والـ Reflectionواجهة IDisposable وجملة usingأساسيات Dependency Injectionتدرّب بنفسك: مترجم C# عبر الإنترنت