title, shortTitle, category, language, tag
| title | shortTitle | category | language | tag | ||
|---|---|---|---|---|---|---|
| Chain of responsibility | Chain of responsibility | Behavioral | ar |
|
أيضًا معروف بـ
- سلسلة الأوامر
- سلسلة الكائنات
- سلسلة المسؤولية
الغرض
يمنع ربط مُرسل الطلب بمستقبله من خلال إعطاء أكثر من كائن الفرصة لإدارة الطلب. يربط الكائنات المستقبلية معًا ويمرر الطلب عبر السلسلة حتى يتمكن أحد الكائنات من معالجته.
الشرح
مثال من الحياة الواقعية
الملك الأورك يعطي أوامر بصوت عالٍ لجيشه. أقرب شخص للرد هو القائد، ثم الضابط، ثم الجندي. القائد، الضابط، والجندي يشكلون سلسلة من المسؤولية.
بكلمات بسيطة
يساعد في بناء سلسلة من الكائنات. يدخل الطلب من طرف ويتنقل عبر كائنات متعددة حتى يجد مديرًا مناسبًا.
تقول ويكيبيديا
في التصميم الموجه للكائنات، نمط سلسلة المسؤولية هو نمط تصميم يتكون من مصدر لأوامر الكائنات وسلسلة من كائنات المعالجة. يحتوي كل كائن معالجة على منطق يحدد أنواع أوامر الكائنات التي يمكنه التعامل معها؛ يتم تمرير البقية إلى كائن المعالجة التالي في السلسلة.
مثال برمجي
ترجمة لمثالنا مع الأورك أعلاه. أولًا، لدينا الكلاس Request:
import lombok.Getter;
@Getter
public class Request {
private final RequestType requestType;
private final String requestDescription;
private boolean handled;
public Request(final RequestType requestType, final String requestDescription) {
this.requestType = Objects.requireNonNull(requestType);
this.requestDescription = Objects.requireNonNull(requestDescription);
}
public void markHandled() {
this.handled = true;
}
@Override
public String toString() {
return getRequestDescription();
}
}
public enum RequestType {
DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX
}
أدناه، نعرض تسلسل هرم مدير الطلبات.
public interface RequestHandler {
boolean canHandleRequest(Request req);
int getPriority();
void handle(Request req);
String name();
}
@Slf4j
public class OrcCommander implements RequestHandler {
@Override
public boolean canHandleRequest(Request req) {
return req.getRequestType() == RequestType.DEFEND_CASTLE;
}
@Override
public int getPriority() {
return 2;
}
@Override
public void handle(Request req) {
req.markHandled();
LOGGER.info("{} handling request \"{}\"", name(), req);
}
@Override
public String name() {
return "Orc commander";
}
}
// يتم تعريف OrcOfficer و OrcSoldier بطريقة مشابهة لـ OrcCommander
الملك أورك يعطي الأوامر ويشكل السلسلة.
public class OrcKing {
private List<RequestHandler> handlers;
public OrcKing() {
buildChain();
}
private void buildChain() {
handlers = Arrays.asList(new OrcCommander(), new OrcOfficer(), new OrcSoldier());
}
public void makeRequest(Request req) {
handlers
.stream()
.sorted(Comparator.comparing(RequestHandler::getPriority))
.filter(handler -> handler.canHandleRequest(req))
.findFirst()
.ifPresent(handler -> handler.handle(req));
}
}
سلسلة المسؤولية في العمل.
var king=new OrcKing();
king.makeRequest(new Request(RequestType.DEFEND_CASTLE,"defend castle"));
king.makeRequest(new Request(RequestType.TORTURE_PRISONER,"torture prisoner"));
king.makeRequest(new Request(RequestType.COLLECT_TAX,"collect tax"));
إخراج وحدة التحكم.
Orc commander handling request "defend castle"
Orc officer handling request "torture prisoner"
Orc soldier handling request "collect tax"
مخطط الفئات
التطبيقية
استخدم سلسلة المسؤولية عندما
- يمكن لعدة كائنات معالجة الطلب، ولا يتم التعرف على المعالج مسبقًا. يجب تحديد المعالج تلقائيًا.
- ترغب في إرسال طلب إلى أحد الكائنات دون تحديد المستقبل بشكل صريح.
- يجب تحديد مجموعة الكائنات التي يمكنها معالجة الطلب ديناميكيًا.
الاستخدامات المعروفة
- التفاعل مع الأحداث في إطارات واجهات المستخدم الرسومية حيث يمكن معالجة الحدث في عدة مستويات من تسلسل مكونات واجهة المستخدم.
- إطارات عمل الوسطاء حيث يمر الطلب عبر سلسلة من كائنات المعالجة.
- أنظمة السجلات حيث يمكن أن تمر الرسائل عبر سلسلة من المسجلين، مع إمكانية معالجتها بطرق مختلفة.
- java.util.logging.Logger#log()
- Apache Commons Chain
- javax.servlet.Filter#doFilter()
العواقب
المزايا:
- تقليل الترابط. لا يحتاج مُرسل الطلب إلى معرفة المعالج المحدد الذي سيعالج الطلب.
- مرونة أكبر في تخصيص المسؤوليات للكائنات. يمكن إضافة أو تغيير المسؤوليات لإدارة الطلب عن طريق تغيير أعضاء وترتيب السلسلة.
- يتيح تعيين معالج افتراضي إذا لم يكن هناك معالج محدد يمكنه معالجة الطلب.
العيوب:
- قد يكون من الصعب تصحيح الأخطاء وفهم التدفق، خاصة إذا كانت السلسلة طويلة ومعقدة.
- قد يبقى الطلب دون معالجة إذا كانت السلسلة لا تحتوي على معالج "التقاط الكل".
- قد تنشأ مشكلات في الأداء بسبب إمكانية مرور الطلب عبر عدة معالجات قبل العثور على المعالج المناسب، أو عدم العثور عليه على الإطلاق.
الأنماط ذات الصلة
- الأمر: يمكن استخدامه لتغليف طلب ككائن، يمكن تمريره عبر السلسلة.
- التركيب: غالبًا ما يتم تطبيق نمط سلسلة المسؤولية مع نمط التركيب.
- الزخرفة: يمكن ربط الزخارف بشكل مشابه للمسؤوليات في نمط سلسلة المسؤولية.
