1. ما هو نمط الاستراتيجية

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

2. الخصائص والمزايا لنمط الاستراتيجية

يحتوي نمط الاستراتيجية على الخصائص والمزايا التالية:

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

3. أمثلة لتطبيقات عملية لنمط الاستراتيجية

يُستخدم نمط الاستراتيجية على نطاق واسع في السيناريوهات التالية:

  • وسائل الدفع المختلفة، مثل الدفع من خلال الآلي باي أو وي شات باي، إلخ.
  • خوارزميات الترتيب المختلفة، مثل فقاعة الترتيب، فرز سريع، إلخ.
  • طرق تسجيل البيانات المختلفة، مثل إخراج الوحدة، إخراج الملف، إلخ.

4. تنفيذ نمط الاستراتيجية في جو لانج

في هذا القسم، سنقوم بتنفيذ نمط الاستراتيجية باستخدام جو لانج وتوفير أمثلة مقابلة ورسوم بيانية لفئات يو أم أل، وتعليقات الكود.

4.1. تخطيط فئات يو أم أل

إليك الرسم البياني لفئات يو أم أل لنمط الاستراتيجية في جو لانج:

Golang Strategy Pattern

4.2. مقدمة للمثال

من الرسم البياني لفئات يو أم أل أعلاه، يمكننا رؤية الأدوار الثلاثة لنمط الاستراتيجية: واجهة الاستراتيجية، فئات الاستراتيجية المحددة (على سبيل المثال، ConcreteStrategyA و ConcreteStrategyB)، وفئة السياق Context.

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

4.3. تنفيذ الخطوة 1: تعريف واجهة الاستراتيجية وفئات الاستراتيجية المحددة

أولاً، نحتاج إلى تعريف واجهة الاستراتيجية Strategy، التي تشمل طريقة Execute(data interface{}) string لتنفيذ الاستراتيجية المحددة.

type Strategy interface {
    Execute(data interface{}) string
}

type ConcreteStrategyA struct{}

func (s *ConcreteStrategyA) Execute(data interface{}) string {
    // منطق تنفيذ الاستراتيجية المحددة A
}

type ConcreteStrategyB struct{}

func (s *ConcreteStrategyB) Execute(data interface{}) string {
    // منطق تنفيذ الاستراتيجية المحددة B
}

4.4. تنفيذ الخطوة 2: تنفيذ فئة السياق

بعد ذلك، نحتاج إلى تنفيذ فئة السياق Context، التي تغلف الكائن الاستراتيجي المحدد، وتوفر طريقة SetStrategy(strategy Strategy) لتعيين الكائن الاستراتيجي، بالإضافة إلى الطريقة ExecuteStrategy(data interface{}) string لتنفيذ الاستراتيجية المحددة.

type Context struct {
    strategy Strategy
}

func (c *Context) SetStrategy(strategy Strategy) {
    c.strategy = strategy
}

func (c *Context) ExecuteStrategy(data interface{}) string {
    if c.strategy == nil {
        // منطق تنفيذ الاستراتيجية الافتراضية
    } else {
        return c.strategy.Execute(data)
    }
}

4.5. تنفيذ الخطوة 3: استخدام نمط الاستراتيجية لإكمال المنطق التجاري الفعلي

أخيرًا، يمكننا استخدام نمط الاستراتيجية في العميل لإكمال المنطق التجاري الفعلي.

func main() {
    context := &Context{}

    // تعيين الاستراتيجية المحددة A باستخدام الطريقة SetStrategy
    context.SetStrategy(&ConcreteStrategyA{})
    result := context.ExecuteStrategy("دفع من خلال الألي باي")

    // تعيين الاستراتيجية المحددة B باستخدام الطريقة SetStrategy
    context.SetStrategy(&ConcreteStrategyB{})
    result = context.ExecuteStrategy("دفع من خلال وي شات باي")
}

الاستنتاج

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