انتقال للمقال

Strategy Pattern خبير الاستراتيجيات الذكي

السلام عليكم ورحمة الله وبركاته

وقت القراءة: ≈ 10 دقائق

المقدمة

اليوم سنتعلم كيف نصمم نظامًا ذكيًا يتكيف مع التغييرات بسهولة وسلاسة دون الحاجة لتعديل الكود الأساسي بشكل متكرر
وسنفعل ذلك باستخدام الـ Strategy Pattern وهو أحد الـ Design Patterns وهو يندرج تحت عائلة الـ Behavioral Design Patterns

والـ Behavioral Design Patterns بشكل عام تهتم بكيفية تفاعل الكلاسات مع بعضها البعض وكيفية تبادل البيانات بينها بشكل سلس
والـ Strategy Pattern هوأحد تلك الطرق التي تساعدنا على تحقيق ذلك
في هذا المقال، سنستعرض كيف يمكننا استخدام الـ Strategy Pattern لجعل تطبيقاتنا أكثر مرونة وقابلية للتوسع

والـ Strategy Pattern يساعدنا على الاختيار والتبديل السلس بين الخوارزميات سواء كانت في الدوال أو الكلاسات المختلفة في اثناء الـ Runtime
وسنرى هذا في الأمثلة العملية التي سنقوم بها في هذا المقال

لكن بالطبع قبل أن نبدأ في شرح الـ Strategy Pattern، دعونا نتعرف على المشكلة التي يقوم بحلها

المشكلة التي يحلها الـ Strategy Pattern

تخيل أنك مطالب بارسال بعض التقارير عن النظام
وكل تقرير يقوم بارسال بيانات مختلفة واحصائيات مختلفة

فقد يكون لديك تقارير مثل:

  1. تقرير عن المبيعات الشهرية
  2. تقرير عن الزبائن الجدد
  3. تقرير عن المنتجات الأكثر مبيعًا
  4. تقرير عن الشحنات المتأخرة
  5. تقرير عن الشحنات التي تم تسليمها
  6. تقرير عن الشحنات التي لم يتم تسليمها
  7. تقرير عن الشحنات التي تم إلغاؤها
  8. ... إلخ

تقارير كثيرة وكل تقرير له طريقة مختلفة في جمع البيانات وحسابها بشكل مختلف
فقد يكون لديك كلاس يدير عملية جمع البيانات، ستسميه ReportGenerator والذي سيحتوي على دالة generate التي تأخذ نوع التقرير

class ReportGenerator {
  generate(reportType: string): void {
    if (reportType === 'monthlySales') {
      // جلب بيانات المبيعات من قاعدة البيانات
      // حساب إجمالي المبيعات والأرباح
      // إنشاء التقرير وعرضه
    } else if (reportType === 'newCustomers') {
      // جلب بيانات الزبائن الجدد من قاعدة البيانات
      // حساب عدد الزبائن الجدد في الشهر
      // إنشاء التقرير وعرضه
    } else if (reportType === 'mostSoldProducts') {
      // جلب بيانات المبيعات لكل منتج
      // ترتيب المنتجات حسب كمية المبيعات
      // إنشاء تقرير بالمنتجات الأكثر مبيعًا
    } else if (reportType === 'delayedShipments') {
      // جمع بيانات الشحنات المتأخرة
      // تحليل أسباب التأخير
      // إنشاء تقرير بالإجراءات المطلوبة
    } else if (reportType === 'deliveredShipments') {
      // جمع بيانات الشحنات التي تم تسليمها
      // حساب نسبة الشحنات التي تم تسليمها بنجاح
      // إنشاء تقرير بالشحنات التي تم تسليمها
    } else if (reportType === 'undeliveredShipments') {
      // جمع بيانات الشحنات التي لم يتم تسليمها
      // تحليل أسباب عدم التسليم
      // إنشاء تقرير بالشحنات التي لم يتم تسليمها
    } else if (reportType === 'canceledShipments') {
      // جمع بيانات الشحنات التي تم إلغاؤها
      // تحليل أسباب الإلغاء
      // إنشاء تقرير بالشحنات التي تم إلغاؤها
    } else {
      throw new Error('Invalid report type');
    }
  }
}

هل يمكنك تخيل المشاكل التي ستواجهها هنا؟
أولًا ستقول لي أن هناك الكثير من الأكواد المختلفة في دالة واحدة وهذاالكثير من المباديء البرمجية
مثل مبدأ Single Responsibility Principle الذي ينص على أن كل كلاس أو دالة يجب أن تكون مسؤولة عن شيء واحد فقط
أما هنا سترى أن عدة عمليات مختلفة عن بعضها البعض مثل generate monthly sales و generate new customers و generate most sold products كلها موجودة في دالة واحدة وهذا يتعارض مع مبدأ Single Responsibility Principle

وأيضًا الدالة تتعارض مع مبدأ Open/Closed Principle الذي ينص على أن الكلاسات يجب أن تكون مفتوحة للتوسع ومغلقة للتعديل
أما هنا فكل شيء في دالة واحدة وفي كلاس واحد
فلو أردنا إضافة أو حذف أو تعديل أي تقرير، سنضطر لتعديل الدالة generate في كل مرة

والدالة generate ستصبح أكبر وأكبر مع مرور لذا التعديل فيها سيصبح صعبًا جدًا لأن هناك الكثير من الأكواد المختلفة والمتداخلة في دالة واحدة
وتعديل شيء واحد قد يجعلك دون قصد تفسد شيء آخر، فبدلًا من أن تعدل تقرير واحد ستجد نفسك قد أفسدت أكواد أخرى في التقارير الأخرى دون أن تدري


يمكننا ان نلخص المشاكل التي سنواجهها في النقاط التالية:

  • عدم الالتزام بمبدأ Single Responsibility Principle بحيث أن الدالة generate تقوم بكل شيء من جلب بيانات وتمعالجتها وعرضها وتقوم بهذا لعدة تقارير مختلفة
  • عدم الالتزام بمبدأ Open/Closed Principle بحيث أنك تضطر لتعديل الدالة generate في كل مرة تريد فيها إضافة أو حذف أو تعديل أي تقرير
  • زيادة تعقيد الدالة generate مع مرور الوقت، مما يجعل من الصعب فهمها وتعديلها
  • زيادة فرص حدوث الأخطاء، حيث أن أي تعديل في الدالة generate قد يؤثر على التقارير الأخرى دون قصد
  • ... إلخ

هنا بالطبع لا داعي لأن أخبركم أن من سيحل هذه المشكلة هو بالطبع بطلنا المغوار وخبير الاستراتيجيات الذكي الـ Strategy Pattern
الذي سيساعدنا على فصل كل خوارزمية أو سلوك مختلف في كلاس منفصل، مما يجعل من السهل علينا إضافة أو حذف أو تعديل أي خوارزمية دون التأثير على الكلاسات الأخرى، وهو يعد تطبيق عملي ومباشر لمبدأ Open/Closed Principle

بطبع كل مباديء الـ SOLID شرحناها في مقالة مبادئ الـ SOLID لجعل كودك صلب كالحديد
شرحنا فيها كل مبدأ من مباديء الـ SOLID وكيفية تطبيقه في الكود بأمثلة عملية

ما هو الـ Strategy Pattern ؟

هو ببساطة طريقة لتقسيم الخوارزميات والأكواد المختلفة في كلاسات منفصلة، بحيث يمكننا استبدالها والتبديل بين تلك الخوارزميات بسهولة ودون الحاجة لتعديل الكود الأساسي

وهو ببساطة يتكون من 3 مكونات رئيسية:

  1. Strategy Interface: الـ Interface الأساسي الذي سيكون الشكل العام لكل كلاس من الاستراتيجيات المختلفة
    وفي حالتنا سيكون لدينا ReportStrategy الذي سيحتوي على دالة generate التي ستقوم بجلب البيانات ومعالجتها وعرضها
    أو يمكننا أن نقسمها إلى 3 دوال مختلفة، بحيث تكون لدينا دالة fetchData لجلب البيانات ودالة processData لمعالجة البيانات ودالة displayData لعرض البيانات
    ويمكننا جعل الدالة generate تقوم باستدعاء تلك الدوال الثلاثة على التوالي
  2. Concrete Strategies: الكلاسات التي تنفذ الـ Interface وتقوم بتطبيق الخوارزمية المختلفة
    وفي حالتنا كل كلاس سيهتم بتنفيذ عملية واحدة، بالتالي سيكون لدينا:
    • NewCustomersReportStrategy
    • MonthlySalesReportStrategy
    • MostSoldProductsReportStrategy
    • DelayedShipmentsReportStrategy
    • DeliveredShipmentsReportStrategy
    • ... إلخ وكل كلاس سيقوم بتنفيذ دالة generate الخاصة به والتي ستقوم بجلب البيانات ومعالجتها وعرضها
  3. Context: الكلاس الذي يستخدم الاستراتيجية المختارة
    وهو الكلاس الأساسي الذي سيختار الاستراتيجية المناسبة ويقوم باستدعاء الدالة generate الخاصة
    ويستطيع التبديل بين الاستراتيجيات المختلفة في أي وقت، مما يجعل من السهل علينا إضافة أو حذف أو تعديل أي استراتيجية دون التأثير على الكلاسات الأخرى

التطبيق العملي للـ Strategy Pattern

الآن بعد أن فهمنا المكونات الأساسية للـ Strategy Pattern، دعونا نطبقها على مثال التقارير الذي ذكرناه سابقًا

إنشاء الـ Strategy Interface

أولًا سنقوم بإنشاء الـ Interface الأساسي الذي ستنفذه كل الاستراتيجيات الخاصة بالتقارير
لنسميه IReportStrategy، وهو سيكون الشكل العام لكل كلاس من الاستراتيجيات المختلفة الخاصة بكل تقرير

interface IReportStrategy {
  generate(): void;
}

هنا قمنا بعمل interface بسيط يحتوي على دالة generate فقط للتبسيط، لكن يمكنك تقسيمها إلى عدة دوال كما ذكرنا سابقًا
فيمكنك جعلها تحتوي على دالة fetchData لجلب البيانات ودالة processData لمعالجة البيانات ودالة displayData لعرض البيانات
لكن من أجل التبسيط، سنتركها كما هي الآن تحتوي على دالة generate فقط

إنشاء الـ Concrete Strategies

الآن سنقوم بإنشاء الكلاسات التي تنفذ الـ Interface وكل كلاس سيهتم بنوع تقرير معين
والكلاسات التي ستنفذ الـ IReportStrategy نسميها Concrete Strategies
ومن ضمن الكلاسات التي سنقوم بإنشائها هي هي NewCustomersReportStrategy و MonthlySalesReportStrategy و MostSoldProductsReportStrategy و DelayedShipmentsReportStrategy وغيرها حسب الحاجة

class NewCustomersReportStrategy implements IReportStrategy {
  public generate(): void {
    console.log('جاري جمع بيانات العملاء الجدد...');
    // جلب بيانات العملاء الجدد من قاعدة البيانات
    // معالجة البيانات وحساب الإحصائيات
    // عرض التقرير أو إرساله
    console.log('تم إنشاء تقرير العملاء الجدد بنجاح');
  }
}

class MonthlySalesReportStrategy implements IReportStrategy {
  public generate(): void {
    console.log('جاري جمع بيانات المبيعات الشهرية...');
    // جلب بيانات المبيعات من قاعدة البيانات
    // حساب إجمالي المبيعات والأرباح
    // إنشاء المخططات والرسوم البيانية
    console.log('تم إنشاء تقرير المبيعات الشهرية بنجاح');
  }
}

class MostSoldProductsReportStrategy implements IReportStrategy {
  public generate(): void {
    console.log('جاري تحليل بيانات المنتجات الأكثر مبيعًا...');
    // جلب بيانات المبيعات لكل منتج
    // ترتيب المنتجات حسب كمية المبيعات
    // إنشاء قائمة بالمنتجات الأكثر مبيعًا
    console.log('تم إنشاء تقرير المنتجات الأكثر مبيعًا بنجاح');
  }
}

class DelayedShipmentsReportStrategy implements IReportStrategy {
  public generate(): void {
    console.log('جاري تحليل بيانات الشحنات المتأخرة...');
    // جلب بيانات الشحنات المتأخرة
    // تحليل أسباب التأخير
    // إنشاء تقرير بالإجراءات المطلوبة
    console.log('تم إنشاء تقرير الشحنات المتأخرة بنجاح');
  }
}

لاحظ أن كل كلاس يركز على مهمة واحدة فقط وهي إنشاء نوع معين من التقارير
وكل كلاس يحتوي على المنطق والكود الخاص به لجمع ومعالجة وعرض البيانات
وهذا يتماشى مع مبدأ Single Responsibility Principle حيث أن كل كلاس مسؤول عن شيء واحد فقط
وأيضًا يتماشى مع مبدأ Open/Closed Principle حيث يمكنك إضافة كلاس جديد لتقرير جديد وجعله ينفذ IReportStrategy دون الحاجة لتعديل الكود الموجود

إنشاء الـ Context

الآن سنقوم بإنشاء الكلاس الذي سيستخدم الاستراتيجيات المختلفة وهذا الكلام يسمى Context وهو الكلاس الاساسي الذي سيختار الاستراتيجية المناسبة ويقوم باستدعاء الدالة generate الخاصة بها

لنسميه ReportGenerator، وهو سيكون الكلاس الذي يدير عملية إنشاء التقارير
ويحتوي على دالة setStrategy لتغيير الاستراتيجية في أي وقت
ودالة generateReport التي تستدعي الدالة generate من الاستراتيجية الحالية

class ReportGenerator {
  private strategy: IReportStrategy;

  constructor(strategy: IReportStrategy) {
    this.strategy = strategy;
  }

  public setStrategy(strategy: IReportStrategy): void {
    this.strategy = strategy;
  }

  public generateReport(): void {
    this.strategy.generate();
  }
}

هنا قمنا بإنشاء كلاس ReportGenerator الذي ستلاحظ عدة أشياء مهمة فيه:

  • يحتوي على strategy من نوع IReportStrategy
    • هنا سنستخدمه ونستفيد من فكرة الـ Polymorphism حيث أن كل كلاس من الاستراتيجيات المختلفة ينفذ نفس الـ Interface
      لذا فالمتغير strategy يمكن أن يكون من أي نوع من الاستراتيجيات التي تنفذ IReportStrategy
      ولاحظ أننا هنا نتعامل مع interface وهو IReportStrategy ولا نهتم بنوع الاستراتيجية المستخدمة حاليًا وهذا هو مفهوم الـ Abstracting
  • يمكنه استقبال الاستراتيجية من خلال الـ constructor لتحديد الاستراتيجية الافتراضية عند إنشاء object من ReportGenerator لكن يمكننا أيضًا تغييرها لاحقًا
  • يحتوي على دالة setStrategy لتغيير الاستراتيجية في أي وقت وهنا تكمن المرونة في استخدام الـ Strategy Pattern حيث يمكنك تغيير الاستراتيجية في أي وقت حسب الحاجة
  • يحتوي على دالة generateReport التي تستدعي الدالة generate من الاستراتيجية الحالية وبما أن كل الاستراتيجيات تنفذ نفس الـ Interface، فيمكننا استدعاء generate دون الحاجة لمعرفة نوع الاستراتيجية المستخدمة حاليًا

استخدام الـ Strategy Pattern

الآن يمكننا استخدام الـ Strategy Pattern بسهولة

// إنشاء تقرير العملاء الجدد
const newCustomersStrategy = new NewCustomersReportStrategy();
const reportGenerator = new ReportGenerator(newCustomersStrategy);
reportGenerator.generateReport();

// تغيير الاستراتيجية لإنشاء تقرير المبيعات الشهرية
const monthlySalesStrategy = new MonthlySalesReportStrategy();
reportGenerator.setStrategy(monthlySalesStrategy);
reportGenerator.generateReport();

// تغيير الاستراتيجية لإنشاء تقرير المنتجات الأكثر مبيعًا
const mostSoldProductsStrategy = new MostSoldProductsReportStrategy();
reportGenerator.setStrategy(mostSoldProductsStrategy);
reportGenerator.generateReport();

// تغيير الاستراتيجية لإنشاء تقرير الشحنات المتأخرة
const delayedShipmentsStrategy = new DelayedShipmentsReportStrategy();
reportGenerator.setStrategy(delayedShipmentsStrategy);
reportGenerator.generateReport();

هنا قمنا بإنشاء ReportGenerator مع استراتيجية NewCustomersReportStrategy، ثم قمنا بتوليد التقرير الخاص بالعملاء الجدد
ثم لاحقًا قمنا بتغيير الاستراتيجية إلى MonthlySalesReportStrategy وتوليد تقرير المبيعات الشهرية
ثم قمنا بتغيير الاستراتيجية مرة أخرى إلى MostSoldProductsReportStrategy وتوليد تقرير المنتجات الأكثر مبيعًا

شكل آخر للـ Context

يمكنك أيضًا استخدام دالة بسيطة كـ Context بدلًا من كلاس

فالـ Context ليس شرطًا أن يكون كلاس، بل يمكن أن يكون دالة بسيطة تقوم بأخذ enum يمثل نوع التقرير وتقوم بتحديد الاستراتيجية المناسبة بناءً على ذلك

enum ReportType {
  NewCustomers,
  MonthlySales,
  MostSoldProducts,
  DelayedShipments,
}

function generateReport(reportType: ReportType): void {
  let strategy: IReportStrategy;

  switch (reportType) {
    case ReportType.NewCustomers:
      strategy = new NewCustomersReportStrategy();
      break;
    case ReportType.MonthlySales:
      strategy = new MonthlySalesReportStrategy();
      break;
    case ReportType.MostSoldProducts:
      strategy = new MostSoldProductsReportStrategy();
      break;
    case ReportType.DelayedShipments:
      strategy = new DelayedShipmentsReportStrategy();
      break;
    default:
      throw new Error('نوع التقرير غير مدعوم');
  }

  strategy.generate();
}

هنا قمنا بإنشاء دالة generateReport التي تأخذ enum يمثل نوع التقرير وتقوم بتحديد الاستراتيجية المناسبة بناءً على ذلك
داخل الدالة لدينا switch-case يحدد أي استراتيجية يجب استخدامها بناءً على نوع التقرير المرسل
ثم ببساطة نستدعي الدالة generate من الاستراتيجية المحددة

وطريقة الاستخدام ستكون كالتالي:

// استخدام الدالة لتوليد تقرير العملاء الجدد
generateReport(ReportType.NewCustomers);
// استخدام الدالة لتوليد تقرير المبيعات الشهرية
generateReport(ReportType.MonthlySales);
// استخدام الدالة لتوليد تقرير المنتجات الأكثر مبيعًا
generateReport(ReportType.MostSoldProducts);
// استخدام الدالة لتوليد تقرير الشحنات المتأخرة
generateReport(ReportType.DelayedShipments);

بهذه الطريقة، يمكنك استخدام الـ Strategy Pattern لجعل الكود أكثر مرونة وقابلية للتوسع
ويمكنك بسهولة إضافة تقارير جديدة دون الحاجة لتعديل الكود الموجود، فقط قم بإنشاء كلاس جديد ينفذ IReportStrategy
ثم قم بتحديد الاستراتيجية الجديدة في الدالة generateReport أو في كلاس ReportGenerator يحسب الحاجة

فوائد الـ Strategy Pattern

دعونا نتذكر سريعًا الفوائد التي نحصل عليها من استخدام الـ Strategy Pattern في مثال التقارير الذي قمنا به:

تطبيق مبدأ Single Responsibility Principle

كل كلاس أصبح مسؤولًا عن شيء واحد فقط:

  • NewCustomersReportStrategy مسؤول فقط عن تقارير العملاء الجدد
  • MonthlySalesReportStrategy مسؤول فقط عن تقارير المبيعات الشهرية
  • ReportGenerator مسؤول فقط عن إدارة الاستراتيجيات واستدعائها
  • ... إلخ

بالتالي عندما تريد تعديل تقرير معين، يمكنك الذهاب مباشرة إلى الكلاس الخاص به وتعديله دون الحاجة للقلق بشأن تأثير ذلك على التقارير الأخرى
وهذا يجعل الكود أكثر وضوحًا وسهولة في الفهم والتعديل وكل الكلمات الرنانة التي نسمعها

تطبيق مبدأ Open/Closed Principle

الكود أصبح:

  • مفتوحًا للتوسع: يمكنك إضافة أنواع جديدة من التقارير بعمل كلاس جديد ينفذ ReportStrategy
  • مغلقًا للتعديل: لا تحتاج لتعديل الكود الموجود عند إضافة تقارير جديدة، فمثلا لن تقوم بتعديل كلاس ReportGenerator أو الـ IReportStrategy أو حتى الكلاسات الأخرى
    بل فقط تضيف كلاس جديد للتقرير الجديد وتجعله ينفذ IReportStrategy
// إضافة تقرير جديد بدون تعديل أي كود موجود
class InventoryReportStrategy implements ReportStrategy {
  public generate(): void {
    console.log('جاري تحليل بيانات المخزون...');
    // الكود الخاص بالتقرير الجديد
    console.log('تم إنشاء تقرير المخزون بنجاح');
  }
}

// استخدام التقرير الجديد
reportGenerator.setStrategy(new InventoryReportStrategy());
reportGenerator.generateReport();

سهولة التبديل بين الاستراتيجيات

يمكن تغيير الاستراتيجية في أي وقت حسب الحاجة

باستخدام دالة setStrategy في كلاس ReportGenerator، يمكنك التبديل بين الاستراتيجيات المختلفة بسهولة ودون الحاجة لتعديل الكود الأساسي
وهذا يجعل الكود أكثر مرونة وقابلية للتوسع

const reportGenerator = new ReportGenerator(
  new MonthlySalesReportStrategy()
);
// توليد تقرير المبيعات الشهرية
reportGenerator.generateReport();

// تغيير الاستراتيجية إلى تقرير جديد
reportGenerator.setStrategy(new NewCustomersReportStrategy());
reportGenerator.generateReport();

// تغيير الاستراتيجية إلى تقرير آخر
reportGenerator.setStrategy(new MostSoldProductsReportStrategy());
reportGenerator.generateReport();

// تغيير الاستراتيجية إلى تقرير آخر
reportGenerator.setStrategy(new DelayedShipmentsReportStrategy());
reportGenerator.generateReport();

لكن الشيء السلبي هنا في استخدام كلاس ReportGenerator هو أنك مجبر على انك وضع استراتيجية افتراضية عند إنشاء object من ReportGenerator لأول مرة
لأنك قد لا تحتاج إلى استراتيجية افتراضية في بعض الحالات خصوصًا لو كانت التقارير تعتمد على بيانات تلقيها من المستخدم أو من مصدر خارجي

لكن في هذه الحالة يمكنك استخدام الدالة generateReport التي قمنا بإنشائها سابقًا والتي تأخذ enum يمثل نوع التقرير وتقوم بتحديد الاستراتيجية المناسبة بناءً على ذلك بشكل ديناميكي

أول يمكنك ازالة الـ constructor من كلاس ReportGenerator وجعل الدالة setStrategy هي المسؤولة عن تعيين الاستراتيجية الحالية
وفي حالة أنك لم تقم بتعيين استراتيجية، يمكنك جعلها ترمي exception عند استدعاء generateReport أو تعيين استراتيجية افتراضية مثل DefaultReportStrategy التي تقوم بعرض رسالة تفيد بعدم تعيين استراتيجية

class ReportGenerator {
  private strategy: IReportStrategy | null = null;

  public setStrategy(strategy: IReportStrategy): void {
    this.strategy = strategy;
  }

  public generateReport(): void {
    if (!this.strategy) {
      throw new Error('لم يتم تعيين استراتيجية للتقرير'); // أو يمكنك تعيين استراتيجية افتراضية هنا
    }
    this.strategy.generate();
  }
}

الختام

الـ Strategy Pattern يعد من أقوى الـ Design Patterns التي تساعدك على كتابة كود سلس ومرن وقابل للتوسع بشكل كبير دون مشاكل أو تعقيدات

فهو يمكنك من:

  • فصل الخوارزميات المختلفة في كلاسات منفصلة وهذا يتماشى مع مبدأ Single Responsibility Principle
  • التبديل بين الخوارزميات أثناء الـ Runtime بسهولة وهو تطبيق مباشر لفكرة الـ Polymorphism و الـ Abstracting
  • إضافة خوارزميات جديدة بدون تعديل الكود الموجود لأنه يطبق مبدأ Open/Closed Principle

كما رأينا في هذا المقال، الـ Strategy Pattern هو حل عملي لمشاكل حقيقية نواجهها في البرمجة بشكل يومي
فبدلًا من كتابة دوال طويلة مليئة بالـ if-else أو switch-case، يمكننا تنظيم الكود بطريقة أكثر احترافية ومرونة

أنصحك بتطبيق الـ Strategy Pattern في مشاريعك القادمة، وخصوصًا في الأجزاء التي تحتاج منك لتطبيق كود مختلف بحسب status أو action أو type معين
وستلاحظ كم سيصبح الكود أكثر سهولة في الفهم والتعديل وكل الكلام الرنان
وتذكر أن الهدف ليس استخدام الـ Design Patterns لمجرد الاستخدام، بل لحل المشاكل الفعلية وتحسين جودة الكود
لأنه أحيانًا قد يكون استخدام الـ Design Patterns غير ضروري أو حتى مضر إذا لم يكن هناك حاجة فعلية له وهذا حصل معي في بعض المشاريع التي عملت عليها

أتمنى أن يكون هذا المقال قد أعطى فكرة واضحة عن الـ Strategy Pattern وكيفية استخدامه في البرمجة