Factory Constructor In Dart

✅ أولًا: ما هو Factory Constructor؟
🔹 التعريف:

هو نوع خاص من الـ constructor يسمح لك بالتحكم الكامل في طريقة إنشاء الكائن (object).
يمكن أن يُرجع كائن جديد، أو يعيد كائن موجود سابقًا، أو حتى يرجع كائن من نوع مختلف.

✅ لماذا نستخدم factory؟
السببالتوضيح
🔁 إعادة استخدام كائن موجودمثل Singleton (كائن واحد فقط)
🔍 تنفيذ منطق قبل إنشاء الكائنمثل التحقق من صحة البيانات
🔄 إرجاع نوع مختلف أو nullمثل تحويل JSON إلى كائن معين
🧠 تحسين الأداء والذاكرةعدم إنشاء أكثر من نسخة من نفس الكائن
✅ الشكل العام:
class MyClass {
  factory MyClass() {
    // منطق مخصص
    return ...; // ترجع كائن من نفس النوع أو نوع مختلف
  }
}
Dart
✅ الفرق بين factory و constructor العادي
المقارنةConstructor العاديFactory Constructor
ينشئ كائن جديد دائمًا؟✅ نعم❌ ليس دائمًا
يمكنه إرجاع نوع مختلف؟❌ لا✅ نعم
يمكنه استخدام return؟❌ لا✅ نعم
مفيد للتحكم الكامل بالإنشاء؟❌ لا✅ نعم
✅ مثال 1: التحقق من صحة البيانات
class User {
  final String name;

  User._(this.name); // private constructor

  factory User(String name) {
    if (name.isEmpty) {
      throw Exception("الاسم لا يمكن أن يكون فارغًا");
    }
    return User._(name);
  }
}

void main() {
  var user = User("Ali"); // ✅ يعمل
  // var user2 = User(""); // ❌ سيرمي Exception
}
Dart
✅ الشرح:
  • أنشأنا constructor داخلي User._ خاص.
  • استخدمنا factory لفحص الاسم أولًا.
  • إذا الاسم غير صالح → نرمي خطأ، وإلا ننشئ الكائن.
✅ مثال 2: Singleton – كائن واحد فقط
class Logger {
  static final Logger _instance = Logger._internal();

  Logger._internal(); // private

  factory Logger() {
    return _instance;
  }

  void log(String msg) => print("LOG: $msg");
}

void main() {
  var l1 = Logger();
  var l2 = Logger();

  print(identical(l1, l2)); // true ✅ نفس الكائن
}
Dart
✅ الشرح:
  • Logger._internal هو constructor داخلي خاص.
  • factory Logger() يرجع دائمًا نفس النسخة المخزنة.
  • هذا هو نمط Singleton.
✅ مثال 3: من JSON إلى كائن
class Product {
  final String name;
  final double price;

  Product(this.name, this.price);

  factory Product.fromJson(Map<String, dynamic> json) {
    return Product(json['name'], json['price']);
  }
}

void main() {
  var json = {'name': 'Keyboard', 'price': 99.99};
  var p = Product.fromJson(json);

  print(p.name); // Keyboard
}
Dart
✅ الشرح:
  • fromJson هي دالة factory.
  • تحول JSON إلى كائن Product.
  • تستخدم كثيرًا في التطبيقات الحقيقية (APIs).
✅ مثال 4: إرجاع نوع فرعي (Subclass)
abstract class Shape {
  void draw();
}

class Circle extends Shape {
  @override
  void draw() => print("رسم دائرة 🟢");
}

class Square extends Shape {
  @override
  void draw() => print("رسم مربع 🟥");
}

class ShapeFactory {
  factory ShapeFactory(String type) {
    if (type == 'circle') return Circle();
    if (type == 'square') return Square();
    throw Exception("شكل غير معروف");
  }
}

void main() {
  Shape s1 = ShapeFactory("circle");
  s1.draw(); // رسم دائرة 🟢
}
Dart
✅ الشرح:
  • ShapeFactory هو factory constructor يرجع نوع مختلف (Circle أو Square).
  • مفيد جدًا لتطبيق مبدأ polymorphism.
✅ ملخص: متى تستخدم factory constructor؟
الحالةاستخدم factory؟
تريد فحص أو معالجة قبل إنشاء الكائن
تريد إرجاع كائن موجود مسبقًا (singleton)
تريد إرجاع كائن من نوع فرعي أو مختلف
تريد تحويل JSON إلى كائن
لا تريد إنشاء أكثر من نسخة من نفس الكائن
✅ الفرق الفني بينهم:
class A {
  A(); // عادي
  factory A.named() {  } // factory
}
Dart
الفرقconstructor عاديfactory constructor
كلمة factory؟❌ لا✅ نعم
يحتوي return؟❌ لا✅ نعم
يتحكم بالإنشاء؟❌ لا✅ نعم
يقدر يرجع كائن من نوع مختلف؟❌ لا✅ نعم