شرح Chain of Responsibility Design Pattern بالتفصيل – فهم نمط سلسلة المسؤولية في Java مع مثال عملي
عند بناء أنظمة تحتوي على مجموعة كبيرة من الشروط أو الفلاتر المتتابعة، يصبح تنظيم الكود تحديًا حقيقيًا. هنا يظهر دور Chain of Responsibility Design Pattern أو نمط سلسلة المسؤولية، والذي يُعد من أهم الأنماط السلوكية (Behavioral Design Patterns) في البرمجة كائنية التوجه (OOP).
يسمح هذا النمط بتمرير الطلبات عبر سلسلة من المعالجات (Handlers)، بحيث يستطيع كل معالج إما معالجة الطلب أو تمريره إلى المعالج التالي في السلسلة دون معرفة من سيعالجه فعليًا.
ما هو Chain of Responsibility Design Pattern؟
Chain of Responsibility Design Pattern هو نمط تصميم سلوكي يسمح بتمرير الطلب عبر سلسلة من الكائنات المرتبطة ببعضها، بحيث يفحص كل كائن الطلب ويقرر:
– إما معالجته. – أو تمريره إلى الكائن التالي في السلسلة.
يُستخدم هذا النمط عادةً عندما:
– لا يكون معروفًا مسبقًا من سيعالج الطلب. – يكون هناك عدة شروط متتابعة. – نحتاج إلى مرونة في ترتيب خطوات المعالجة.
مثال عملي بدون استخدام Chain of Responsibility Pattern
public class MessageProcessor {
public void processMessage(String message) {
if (!containsSpam(message)) {
if (!containsVirus(message)) {
if (!isFromBlockedSender(message)) {
System.out.println("Message is clean: " + message);
} else {
System.out.println("Message is from a blocked sender.");
}
} else {
System.out.println("Message contains a virus.");
}
} else {
System.out.println("Message contains spam.");
}
}
private boolean containsSpam(String message) {
return message.contains("spam");
}
private boolean containsVirus(String message) {
return message.contains("virus");
}
private boolean isFromBlockedSender(String message) {
return message.contains("blocked@domain.com");
}
}
// الاستخدام
MessageProcessor processor = new MessageProcessor();
processor.processMessage("This is a clean message.");
عيوب الكود بدون استخدام Chain of Responsibility
تداخل الشروط (Nested Conditions):
كلما زادت الشروط أصبح الكود أكثر تعقيدًا وأقل وضوحًا.
صعوبة التوسيع:
إضافة فلتر جديد يتطلب تعديل الكود الأساسي.
انتهاك مبدأ Single Responsibility:
الكلاس الواحد يتحمل مسؤوليات متعددة.
مثال عملي باستخدام Chain of Responsibility Design Pattern
abstract class MessageHandler {
protected MessageHandler next;
public void setNext(MessageHandler next) {
this.next = next;
}
public void handle(String message) {
if (next != null) {
next.handle(message);
}
}
}
class SpamFilterHandler extends MessageHandler {
@Override
public void handle(String message) {
if (message.contains("spam")) {
System.out.println("Message contains spam.");
} else {
super.handle(message);
}
}
}
class VirusFilterHandler extends MessageHandler {
@Override
public void handle(String message) {
if (message.contains("virus")) {
System.out.println("Message contains a virus.");
} else {
super.handle(message);
}
}
}
class BlockedSenderFilterHandler extends MessageHandler {
@Override
public void handle(String message) {
if (message.contains("blocked@domain.com")) {
System.out.println("Message is from a blocked sender.");
} else {
super.handle(message);
}
}
}
// الاستخدام
MessageHandler spamFilter = new SpamFilterHandler();
MessageHandler virusFilter = new VirusFilterHandler();
MessageHandler blockedSenderFilter = new BlockedSenderFilterHandler();
spamFilter.setNext(virusFilter);
virusFilter.setNext(blockedSenderFilter);
spamFilter.handle("This is a clean message.");
شرح آلية العمل
– يتم أولاً إنشاء abstract class يحتوي على المرجع للمعالج التالي (next) ودالة handle. – كل فلتر (Spam – Virus – Blocked Sender) يرث من MessageHandler. – كل معالج يتحقق من شرطه الخاص. – إذا لم يتحقق الشرط، يتم تمرير الطلب إلى المعالج التالي. – في الاستخدام، نقوم بربط المعالجات ببعضها باستخدام setNext.
عند استدعاء:
spamFilter.handle(“This is a clean message.”);
تمر الرسالة عبر جميع الفلاتر بالتتابع حتى تصل إلى النهاية.
الفرق بين الطريقتين
بدون Chain of Responsibility:
– شروط متداخلة ومعقدة.
– صعوبة في التوسيع.
– مركزية منطق التنفيذ في مكان واحد.
باستخدام Chain of Responsibility Design Pattern:
– فصل المسؤوليات بين المعالجات.
– سهولة إضافة فلتر جديد دون تعديل الكود القديم.
– مرونة في تغيير ترتيب التنفيذ.
– كود أنظف وأكثر قابلية للصيانة.
مميزات Chain of Responsibility Design Pattern
سهولة التوسيع:
يمكن إضافة معالج جديد دون التأثير على باقي النظام.
تنظيم أفضل للكود:
كل كلاس مسؤول عن شرط واحد فقط.
قابلية إعادة الاستخدام:
يمكن إعادة استخدام أي معالج في سياق آخر.
مرونة عالية:
يمكن تغيير ترتيب السلسلة بسهولة.
عيوب Chain of Responsibility Design Pattern
صعوبة تتبع التنفيذ:
قد يكون من الصعب معرفة أي معالج قام بمعالجة الطلب.
احتمال عدم معالجة الطلب:
إذا لم يعالج أي معالج الطلب ولم يتم التعامل مع الحالة النهائية.
زيادة عدد الكلاسات:
قد يؤدي إلى زيادة عدد الملفات في المشاريع الكبيرة.
متى نستخدم Chain of Responsibility؟
يُستخدم هذا النمط غالبًا في:
– أنظمة الفلترة (مثل البريد الإلكتروني).
– أنظمة التحقق Validation Systems.
– أنظمة الموافقات Approval Workflows.
– Middleware في تطبيقات الويب.
الخلاصة
Chain of Responsibility Design Pattern هو نمط قوي لتنظيم معالجة الطلبات المعقدة بطريقة مرنة وقابلة للتطوير.
فكر فيه كسلسلة من الفلاتر، كل فلتر يتحقق من شرط معين، وإذا لم يجد مشكلة يمرر الطلب إلى التالي.
(تمرير الطلبات عبر سلسلة من المعالجات بحيث يمكن لكل معالج إما معالجة الطلب أو تمريره إلى المعالج التالي)
إذا كنت تبني نظامًا يحتوي على العديد من شروط التحقق أو خطوات المعالجة المتتابعة، فإن هذا النمط سيجعل كودك أكثر احترافية وقابلية للصيانة على المدى الطويل.
يمكنك ايضا الاطلاع علي Factory Design Pattern بالتفصيل مع مثال توضيحي
رابط المقال



