نمط الاستراتيجية في كوكب Kawkab
نمط الاستراتيجية (Strategy Pattern) هو واحد من أنماط التصميم السلوكية التي تتيح لك عزل الخوارزميات المختلفة داخل كائنات مستقلة وقابلة للتبديل بسهولة. في إطار العمل كوكب Kawkab، يُمكنك استخدام هذا النمط لتعزيز مرونة التطبيق، وفصل الخوارزميات عن الكائنات التي تعتمد عليها.
ما هو نمط الاستراتيجية؟
ببساطة، يُمكّنك نمط الاستراتيجية من:
- تعريف مجموعة خوارزميات منفصلة لكل حالة معينة.
- تبديل الخوارزمية المستخدمة أثناء التشغيل (runtime) دون التأثير على الكائنات الأخرى.
- تقليل التكرار وجعل الكود أكثر قابلية للتوسع والصيانة.
متى تستخدم نمط الاستراتيجية؟
- عندما يكون لديك عدة طرق أو خوارزميات لحل مشكلة معينة.
- عندما تحتاج إلى تبديل سلوك الكائنات أثناء التشغيل.
- لتجنب العبارات الشرطية الطويلة (مثل
if-else
أوswitch-case
).
إنشاء استراتيجية جديدة في كوكب Kawkab
أمر الإنشاء
لإضافة استراتيجية جديدة بسهولة في كوكب Kawkab، يتم توفير أمر مخصص:
npm run kawkab strategy:make <name> [module]
المعلمات:
<name>
: اسم الاستراتيجية (مثلpayment
،authentication
).[module]
(اختياري): الوحدة التي ستُضاف إليها الاستراتيجية. إذا لم تحدد الوحدة، ستوضع الاستراتيجية ضمن الوحدة الافتراضيةmain
.
مثال عملي:
npm run kawkab strategy:make payment
هذا المثال سيُنتج:
- واجهة تعريف للاستراتيجية
IStrategy.ts
. - فئة إدارة الاستراتيجية
PaymentStrategy.ts
. - تنفيذ أولي لاستراتيجية محددة
StrategyA.ts
.
هيكل الملفات الناتج
1. واجهة الاستراتيجية (IStrategy.ts
)
تُعرف الواجهة العقد (Contract) الذي يجب أن تلتزم به جميع الاستراتيجيات:
export interface IStrategy {
execute(): void;
}
2. فئة الاستراتيجية الرئيسية (PaymentStrategy.ts
)
تحتوي على المنطق المسؤول عن تحديد واستخدام الاستراتيجية المطلوبة:
import { IStrategy } from './IStrategy';
import { StrategyA } from './StrategyA';
export class PaymentStrategy {
private strategy: IStrategy;
constructor(strategy: IStrategy) {
this.strategy = strategy;
}
static StrategyA(): PaymentStrategy {
return new PaymentStrategy(new StrategyA());
}
execute(): void {
return this.strategy.execute();
}
}
3. تنفيذ الاستراتيجية المحددة (StrategyA.ts
)
هنا يتم كتابة منطق الخوارزمية المحددة للاستراتيجية:
import { IStrategy } from './IStrategy';
export class StrategyA implements IStrategy {
execute(): void {
console.log('Executing Strategy A...');
// منطق الاستراتيجية هنا
}
}
كيفية استخدام الاستراتيجية؟
تطبيق استراتيجيات في وحدة تحكم
لنفرض أننا نريد استخدام استراتيجية تسجيل دخول (LoginStrategy
):
import { BaseController, inherit } from "kawkab";
import { LoginStrategy } from "../strategies/login/LoginStrategy";
export default class extends inherit(BaseController) {
async post() {
// تطبيق الاستراتيجية A
const strategy = LoginStrategy.StrategyA();
strategy.execute();
return {
status: true,
message: "Strategy executed successfully!"
};
}
}
شرح الكود:
LoginStrategy.StrategyA()
: ينشئ مثيلًا للاستراتيجية باستخدامStrategyA
.execute()
: ينفذ منطق الاستراتيجية المحددة.
إضافة استراتيجية جديدة: StrategyB
1. إنشاء ملف الاستراتيجية الجديدة
قم بإنشاء ملف جديد داخل مجلد الاستراتيجيات بنفس الوحدة (مثلاً strategies/login
) واسمه StrategyB.ts
.
محتوى ملف StrategyB.ts
:
import { IStrategy } from './IStrategy';
export class StrategyB implements IStrategy {
execute(): void {
console.log('Executing Strategy B...');
// منطق الاستراتيجية B
}
}
2. تحديث الفئة الرئيسية للاستراتيجيات
قم بتحديث فئة LoginStrategy
لتدعم اختيار الاستراتيجية الجديدة StrategyB
.
الكود المحدث لـ LoginStrategy.ts
:
import { IStrategy } from './IStrategy';
import { StrategyA } from './StrategyA';
import { StrategyB } from './StrategyB';
export class LoginStrategy {
private strategy: IStrategy;
constructor(strategy: IStrategy) {
this.strategy = strategy;
}
// إضافة دعم لاستراتيجية A
static StrategyA(): LoginStrategy {
return new LoginStrategy(new StrategyA());
}
// إضافة دعم لاستراتيجية B
static StrategyB(): LoginStrategy {
return new LoginStrategy(new StrategyB());
}
execute(): void {
return this.strategy.execute();
}
}
3. استخدام استراتيجية B
داخل وحدة تحكم (Controller):
يمكنك الآن استخدام StrategyB
بنفس الطريقة التي تستخدم بها الاستراتيجيات الأخرى:
import { BaseController, inherit } from "kawkab";
import { LoginStrategy } from "../strategies/login/LoginStrategy";
export default class extends inherit(BaseController) {
async post() {
// استخدام استراتيجية B
const strategy = LoginStrategy.StrategyB();
strategy.execute();
return {
status: true,
message: "Strategy B executed successfully!"
};
}
}
كيف يعمل؟
-
LoginStrategy.StrategyB()
: يقوم بإنشاء نسخة جديدة من الاستراتيجية باستخدام الفئةStrategyB
. -
execute()
: ينفذ منطق الخوارزمية المعرّف داخلStrategyB
.
هيكل الملفات بعد الإضافة
/strategies
/login
- IStrategy.ts
- LoginStrategy.ts
- StrategyA.ts
- StrategyB.ts
إضافة خوارزميات إضافية مستقبلاً
لإضافة استراتيجية جديدة، يمكنك تكرار نفس الخطوات:
- إنشاء فئة جديدة للخوارزمية.
- تعديل الفئة الرئيسية
LoginStrategy
لدعم الاستراتيجية الجديدة.
مزايا نمط الاستراتيجية
-
المرونة والتبديل أثناء التشغيل:
- يمكن تغيير السلوك دون التأثير على الكود الرئيسي.
-
تقليل العبارات الشرطية الطويلة:
- بدلاً من استخدام تراكيب مثل
if-else
، تُدار السلوكيات بواسطة استراتيجيات مستقلة.
- بدلاً من استخدام تراكيب مثل
-
تحسين قابلية التوسع:
- إضافة استراتيجية جديدة يعني ببساطة إنشاء فئة جديدة مع الالتزام بالواجهة.
-
فصل المسؤوليات:
- يُصبح كل كائن مسؤولًا عن تنفيذ منطق محدد فقط.
-
سهولة الاختبار:
- يمكن اختبار كل استراتيجية على حدة دون الحاجة إلى اختبار النظام بأكمله.
أفضل الممارسات
1. هيكلية منظمة
ضع جميع استراتيجيات الوحدة في مجلد خاص بها، مثلاً:
/strategies
/login
- IStrategy.ts
- LoginStrategy.ts
- StrategyA.ts
- StrategyB.ts
2. استخدام واجهات قوية
استخدام واجهات مثل IStrategy
يضمن تجانس الاستراتيجيات وقابليتها للتبديل.
3. تجنب منطق معقد داخل الفئات
اجعل منطق الاستراتيجية بسيطًا وواضحًا وقابلًا للفصل.
الختام
نمط الاستراتيجية يُمثل طريقة مثالية لتبسيط التعامل مع الخوارزميات المتعددة في تطبيقك. في إطار العمل كوكب Kawkab، يوفر هذا النمط أدوات قوية تجعل إنشاء وتبديل السلوكيات أسهل وأكثر تنظيمًا.
💡 ابدأ الآن بتطبيق نمط الاستراتيجية في مشروعك واستمتع بالكود المنظم والمرن!