أنماط التصميم في TypeScript: من البسيط إلى المعقد
أنماط التصميم (design patterns) هي حلول مثبتة عبر الزمن للمشاكل النمطية في تطوير البرمجيات. في سياق TypeScript، الذي يضيف إلى JavaScript كتابة صارمة (strict typing) وإمكانيات البرمجة كائنية التوجه (OOP)، تصبح الأنماط فعالة بشكل خاص. يتيح TypeScript تنفيذ التجريدات (abstractions)، الواجهات (interfaces)، وتعدد الأشكال (polymorphism) على مستوى جديد، مما يجعل الكود أكثر قابلية للتنبؤ وأمانًا.
في هذه المقالة، سنشرح الأنماط الرئيسية للتصميم، وتنفيذها في TypeScript مع أمثلة عملية للاستخدام. ستكون المادة مفيدة لكل من المطورين المبتدئين والمتخصصين ذوي الخبرة الذين يرغبون في تنظيم معرفتهم.
أنماط الإنشاء: Singleton و Factory Method
أنماط الإنشاء مسؤولة عن إنشاء الكائنات، مع إخفاء منطق التهيئة (instantiating). سننظر في اثنين من أشهر الممثلين: Singleton و Factory Method.
Singleton (المفرد)
يضمن Singleton أن يكون للفئة (class) نسخة واحدة فقط، ويوفر نقطة وصول عالمية إليها. في TypeScript، يصبح التنفيذ أنيقًا بشكل خاص بفضل الأعضاء الثابتة (static members) والمُنشئات الخاصة (private constructors).
class DatabaseConnection { private static instance: DatabaseConnection; private connectionString: string;
private constructor(connectionString: string) { this.connectionString = connectionString; console.log(`تم إنشاء اتصال بـ: ${connectionString}`); }
static getInstance(connectionString: string): DatabaseConnection { if (!DatabaseConnection.instance) { DatabaseConnection.instance = new DatabaseConnection(connectionString); } return DatabaseConnection.instance; }
query(sql: string): void { console.log(`تنفيذ الاستعلام: ${sql} على ${this.connectionString}`); }}
// الاستخدامconst db1 = DatabaseConnection.getInstance('postgres://localhost:5432/mydb');const db2 = DatabaseConnection.getInstance('postgres://localhost:5432/mydb');console.log(db1 === db2); // true - نفس الكائنهذا النمط مثالي لإدارة الموارد: مجموعات الاتصالات (connection pools)، التسجيل (logging)، التخزين المؤقت (caching). لكن كن حذرًا — قد يعقد Singleton عملية الاختبار بسبب الحالة العالمية (global state).
Factory Method (طريقة المصنع)
يحدد Factory Method واجهة (interface) لإنشاء كائن، لكنه يسمح للفئات الفرعية (subclasses) بتغيير نوع الكائن الذي يتم إنشاؤه. في TypeScript، يتم تنفيذ ذلك عبر الفئات المجردة (abstract classes) أو الواجهات (interfaces).
interface Notification { send(message: string): void;}
class EmailNotification implements Notification { send(message: string): void { console.log(`إرسال بريد إلكتروني: ${message}`); }}
class SMSNotification implements Notification { send(message: string): void { console.log(`إرسال SMS: ${message}`); }}
abstract class NotificationFactory { abstract createNotification(): Notification;
notify(message: string): void { const notification = this.createNotification(); notification.send(message); }}
class EmailFactory extends NotificationFactory { createNotification(): Notification { return new EmailNotification(); }}
class SMSFactory extends NotificationFactory { createNotification(): Notification { return new SMSNotification(); }}
// الاستخدامconst factory: NotificationFactory = new EmailFactory();factory.notify('تم تأكيد طلبك!');يساعد Factory Method في الالتزام بمبدأ الانفتاح/الإغلاق (OCP) — يمكنك إضافة أنواع جديدة من الإشعارات دون تغيير الكود الموجود.
الأنماط الهيكلية: Adapter و Decorator
تساعد الأنماط الهيكلية في تنظيم العلاقات بين الكائنات والفئات، مما يجعل النظام أكثر مرونة وقابلية للتوسع.