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

نمط الاستراتيجية (Strategy Pattern)

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

نمط Strategy pattern هو نمط سلوكي يتيح لك تعريف عائلة من الخوارزميات، وتغليف كل خوارزمية منها في فئتها الخاصة، وجعلها قابلة للتبديل أثناء التشغيل. وبدلًا من ترميز السلوك بشكل ثابت، تحقن الاستراتيجية المطلوبة في كائن.

يتكوّن النمط من ثلاثة أجزاء: واجهة strategy تحدد عقد الخوارزمية، وclassات strategy ملموسة تنفّذ سلوكيات مختلفة، وclass سياق يستخدم strategy:

public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via Credit Card");
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(decimal amount) => 
        Console.WriteLine($"Paid {amount} via PayPal");
}

public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;
    
    public void SetPaymentMethod(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy;
    }
    
    public void Checkout(decimal total)
    {
        _paymentStrategy.Pay(total);
    }
}

لا يعرف السياق (ShoppingCart) طريقة الدفع التي يستخدمها - فهو يستدعي ببساطة Pay() على أي استراتيجية تم توفيرها:

var cart = new ShoppingCart();

cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m);  // تم دفع 99.99 عبر بطاقة الائتمان

cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m);  // تم دفع 49.99 عبر PayPal

يلغي نمط الاستراتيجية المنطق الشرطي المعقد. تعني إضافة طريقة دفع جديدة إنشاء فئة جديدة تنفّذ IPaymentStrategy - ولا حاجة إلى إجراء أي تغييرات في ShoppingCart. وهذا يجعل كودك مفتوحًا للتوسعة لكنه مغلقًا أمام التعديل.

challenge icon

التحدي

سهل

لنبنِ حاسبة لتكلفة الشحن باستخدام نمط Strategy. تمتلك طرق الشحن المختلفة خوارزميات تسعير مختلفة، وينبغي أن يتيح نظامك التبديل بينها أثناء التشغيل دون تغيير منطق معالجة الطلب الأساسي.

ستنظّم كودك عبر ثلاثة ملفات:

  • ShippingStrategy.cs: Define واجهة IShippingStrategy في مساحة الأسماء Shipping مع method CalculateCost(double weight) تُرجع قيمة من النوع double. ثم أنشئ ثلاث فئات استراتيجية Concrete:
    • StandardShipping - تحسب cost وفقًا للمعادلة weight * 1.5
    • ExpressShipping - تحسب cost وفقًا للمعادلة weight * 3.0 + 5.0 (وتتضمن رسومًا ثابتة للشحن السريع)
    • OvernightShipping - تحسب cost وفقًا للمعادلة weight * 5.0 + 10.0 (خدمة متميزة برسوم أساسية أعلى)
  • OrderProcessor.cs: Create فئة OrderProcessor في مساحة الأسماء نفسها. هذه هي فئة Context التي تستخدم استراتيجية شحن. ينبغي أن تحتوي على:
    • field خاص للاحتفاظ بـ IShippingStrategy الحالية
    • method SetShippingMethod(IShippingStrategy strategy) لتغيير استراتيجية الشحن
    • method ProcessOrder(double weight) التي تستخدم الاستراتيجية الحالية لحساب تكلفة الشحن وإرجاعها
  • Program.cs: اجمع كل شيء معًا من خلال إنشاء OrderProcessor وتوضيح كيفية تبديل استراتيجيات الشحن أثناء التشغيل. يمكن للمعالج نفسه حساب التكاليف باستخدام خوارزميات مختلفة بمجرد تغيير استراتيجيته.

ستتلقى مدخلين:

  • نوع طريقة الشحن: standard أو express أو overnight
  • وزن الطرد كرقم عشري (مثلًا: 4.5)

أنشئ OrderProcessor، واضبط استراتيجية الشحن appropriate استنادًا إلى نوع الإدخال، ثم عالج الطلب واطبع cost calculated.

على سبيل المثال، إذا كان الإدخالان هما express و4.5، فينبغي أن يكون الناتج:

18.5

يوضح هذا قوة نمط Strategy - إذ لا يحتوي OrderProcessor على أي منطق لحساب تكلفة الشحن بنفسه. بل يفوّض المهمة ببساطة إلى الاستراتيجية التي أُسنِدت إليه، مما يجعل من السهل إضافة طرق شحن جديدة (مثل DroneDelivery) دون تعديل المعالج إطلاقًا!

جرّب بنفسك

using System;
using Shipping;

class Program
{
    public static void Main(string[] args)
    {
        // اقرأ المدخلات
        string shippingType = Console.ReadLine();
        double weight = Convert.ToDouble(Console.ReadLine());

        // TODO: أنشئ مثيلاً من OrderProcessor

        // TODO: بناءً على shippingType ("standard", "express", or "overnight")،
        // أنشئ استراتيجية الشحن المناسبة وعيّنها على المعالج

        // TODO: عالج الطلب واطبع التكلفة المحسوبة
    }
}
quiz iconاختبر نفسك

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

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

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