استبدال المُنشئ بتابع التصميم (Replace Constructor with Factory Method)

من موسوعة حسوب

المشكلة

لديك مُنشئ (constructor) معقد يقوم بما هو أكثر من مجرد وضع قيم المعامل في حقول الكائن.

الحل

إنشاء تابع تصميم واستخدامه لاستبدال استدعاءات المُنشئ.

مثال

قبل إعادة التصميم

وجود منشئ معقد للصنف Employee:

في لغة Java:

class Employee {
  Employee(int type) {
    this.type = type;
  }
  //...
}

في لغة C#‎:

public class Employee 
{
  public Employee(int type) 
  {
    this.type = type;
  }
  //...
}

في لغة PHP:

class Employee {
  // ...
  public function __construct($type) {
   $this->type = $type;
  }
  // ...
}

في لغة TypeScript:

class Employee {
  constructor(type: number) {
    this.type = type;
  }
  //...
}

بعد إعادة التصميم

إنشاء تابع تصميم واستبداله بالمنشئ:

في لغة Java:

class Employee {
  static Employee create(int type) {
    employee = new Employee(type);
    // نفذ بعض الأمور المعقدة والضخمة هنا
    return employee;
  }
  //...
}

في لغة C#‎:

public class Employee
{
  public static Employee Create(int type)
  {
    employee = new Employee(type);
    // نفذ بعض الأمور المعقدة والضخمة هنا
    return employee;
  }
  //...
}

في لغة PHP:

class Employee {
  // ...
  static public function create($type) {
    $employee = new Employee($type);
    // نفذ بعض الأمور المعقدة والضخمة هنا
    return $employee;
  }
  // ...
}

في لغة TypeScript:

class Employee {
  static create(type: number): Employee {
    let employee = new Employee(type);
    // نفذ بعض الأمور المعقدة والضخمة هنا
    return employee;
  }
  //...
}

لم إعادة التصميم؟

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

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

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

فوائد تطبيق الحل

  • لا يعيد تابع التصميم كائنًا من الصنف الذي أُستُدعيَ منه بالضرورة. وكثيرًا ما يكون من أصنافه الفرعية، مُختارًا بحسب الوسائط المقدمة إلى التابع.
  • يمكن لتابع التصميم أن يكون له اسم أفضل يصف ما يفعله ويعيده وكيف، على سبيل المثال Troops::GetCrew(myTank)‎.
  • يمكن لتابع التصميم أن يعيد كائنًا مُنشَأً بالفعل، على عكس المُنشئ، الذي يخلق دائما نسخة جديدة.

آلية الحل

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

انظر أيضًا

مصادر