تقديم الكائن الفارغ Introduce Null Object
المشكلة
تؤدي إعادة بعض التوابع للقيمة null
بدلًا من الكائنات الحقيقية، لامتلاء الشيفرة البرمجية بالعديد من نقاط التحقق من القيمة null
.
الحل
إعادة كائن فارغ يظهر السلوك الافتراضي بدلًا من null
.
مثال
قبل إعادة التصميم
في لغة Java:
if (customer == null) {
plan = BillingPlan.basic();
}
else {
plan = customer.getPlan();
}
في لغة C#:
if (customer == null)
{
plan = BillingPlan.Basic();
}
else
{
plan = customer.GetPlan();
}
في لغة PHP:
if ($customer == null)
$plan = BillingPlan::basic();
else
$plan = $customer->getPlan();
في لغة Python:
if customer == None:
plan = BillingPlan.basic()
else:
plan = customer.getPlan()
بعد إعادة التصميم
في لغة Java:
class NullCustomer extends Customer {
boolean isNull() {
return true;
}
Plan getPlan() {
return new NullPlan();
}
// بعض وظائف NULL الأخرى.
}
// استبدل القيم الفارغة بالكائن Null.
customer = (order.customer != null) ?
order.customer : new NullCustomer();
// استخدام كائن Null كما لو كان صنف فرعي عادي.
plan = customer.getPlan();
في لغة C#:
public sealed class NullCustomer: Customer
{
public override bool IsNull
{
get { return true; }
}
public override Plan GetPlan()
{
return new NullPlan();
}
// بعض وظائف NULL الأخرى.
}
// استبدل القيم الفارغة بالكائن Null.
customer = order.customer ?? new NullCustomer();
// استخدام كائن Null كما لو كان صنف فرعي عادي.
plan = customer.GetPlan();
في لغة PHP:
class NullCustomer extends Customer {
function isNull() {
return true;
}
function getPlan() {
return new NullPlan();
}
// بعض وظائف NULL الأخرى.
// استبدل القيم الفارغة بالكائن Null.
$customer = ($order->customer != null) ?
$order->customer :
new NullCustomer();
// استخدام كائن Null كما لو كان صنف فرعي عادي.
$plan = $customer->getPlan();
في لغة Python:
class NullCustomer(Customer):
def isNull(self):
return True
def getPlan(self):
return self.NullPlan()
# بعض وظائف NULL الأخرى.
# استبدل القيم الفارغة بالكائن Null.
customer = order.customer if order.customer != None else NullCustomer()
# استخدام كائن Null كما لو كان صنف فرعي عادي.
plan = customer.getPlan()
لم إعادة التصميم؟
تُحيل العشرات من نقاط التحقق من القيمة null
الشيفرةَ البرمجية أطول وأقبح.
مساوئ تطبيق الحل
- يجب إنشاء صنف جديد آخر للتخلص من الشرطيات.
آلية الحل
- أنشئ صنف فرعي للصنف المعني يقوم بدور كائن فارغ.
- في كلا الصنفين، أنشئ التابع
isNull()
الذي يعيدtrue
لكائن فارغ وfalse
للصنف الحقيقي. - ابحث عن جميع الأماكن التي يمكن أن تُعيد فيها
null
للشيفرة بدلًا من كائنٍ حقيقيٍ. وغيَّر الشيفرة البرمجية بحيث تُعيد كائنًا فارغًا. - ابحث عن جميع الأماكن حيث تُقارن متغيرات الصنف الحقيقي مع
null
. واستبدال نقاط التحقق هذه باستدعاءات للتابعisNull().
- إذا نُفذت توابع الصنف الأصلي داخل هذه الشرطيات عندما لا تساوي قيمة ما
null
، أعِد تعريف هذه التوابع في الصنف الفارغ وادرج فيه الشيفرة البرمجية من الجزءelse
من الشرط. ثم يمكنك حذف كامل الشرطية وتنفيذ تغيير السلوك عبر التعددية الشكلية. - إذا لم تكن الأمور بهذه البساطة ولا يمكن إعادة تعريف التوابع، تحقق من إذا كان يمكنك ببساطة استخراج العوامل التي كان من المفترض تنفيذها في حالة القيمة
null
إلى توابع جديدة للكائن الفارغ. واستدعِ هذه التوابع بدلًا من الشيفرة البرمجية القديمة فيelse
كعمليات افتراضية.
- إذا نُفذت توابع الصنف الأصلي داخل هذه الشرطيات عندما لا تساوي قيمة ما