---
title: "سلسلة المسؤوليات"
type: "design-pattern"
slug: "chain-of-responsibility"
url: "http://localhost:3000/ar/design-patterns/chain-of-responsibility.md"
category: "الأنماط السلوكية"
description: "سلسلة المسؤوليات هي نمط تصميم سلوكي يتيح لك تمرير الطلبات عبر سلسلة من المعالجات. عند استقبال طلب، يقرر كل معالج إما معالجة الطلب أو تمريره إلى المعالج التالي في السلسلة."
languages: ["java", "csharp", "cpp", "go", "php", "python", "ruby", "rust", "swift", "typescript"]
---
# سلسلة المسؤوليات

> سلسلة المسؤوليات هي نمط تصميم سلوكي يتيح لك تمرير الطلبات عبر سلسلة من المعالجات. عند استقبال طلب، يقرر كل معالج إما معالجة الطلب أو تمريره إلى المعالج التالي في السلسلة.

## Intent

**سلسلة المسؤوليات** هي نمط تصميم سلوكي يتيح لك تمرير الطلبات عبر سلسلة من المعالجات. عند استقبال طلب، يقرر كل معالج إما معالجة الطلب أو تمريره إلى المعالج التالي في السلسلة.

## Problem

تخيّل أنك تعمل على نظام طلبات إلكتروني. تريد تقييد الوصول إلى النظام بحيث يتمكن المستخدمون المصادَق عليهم فقط من إنشاء الطلبات. كما يجب أن يتمتع المستخدمون الذين لديهم صلاحيات إدارية بوصول كامل إلى جميع الطلبات.

بعد بعض التخطيط، أدركت أن عمليات التحقق هذه يجب أن تُنفَّذ بالتسلسل. يمكن للتطبيق محاولة مصادقة المستخدم على النظام عند استقبال طلب يحتوي على بيانات اعتماده. ومع ذلك، إذا كانت بيانات الاعتماد غير صحيحة وفشلت المصادقة، فلا داعي للمتابعة مع أي عمليات تحقق أخرى.

يجب أن يمر الطلب بسلسلة من عمليات التحقق قبل أن يتمكن نظام الطلبات نفسه من معالجته.

خلال الأشهر القليلة التالية، نفّذت عدة عمليات تحقق تسلسلية إضافية.

* اقترح أحد زملائك أنه من غير الآمن تمرير البيانات الخام مباشرة إلى نظام الطلبات. لذا أضفت خطوة تحقق إضافية لتنقية البيانات في الطلب.
* لاحقًا، لاحظ أحدهم أن النظام عرضة لهجمات تخمين كلمات المرور بالقوة الغاشمة. لتفادي ذلك، أضفت على الفور عملية تحقق تُصفّي الطلبات الفاشلة المتكررة القادمة من نفس عنوان IP.
* اقترح شخص آخر أنك تستطيع تسريع النظام بإعادة النتائج المخزنة مؤقتًا عند الطلبات المتكررة التي تحتوي على نفس البيانات. لذا أضفت عملية تحقق أخرى تسمح للطلب بالمرور إلى النظام فقط إذا لم يكن هناك استجابة مخزنة مؤقتًا مناسبة.

كلما نما الكود، ازدادت فوضاه.

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

أصبح النظام صعب الفهم جدًا ومكلف الصيانة. كافحت مع الكود لبعض الوقت، حتى قررت ذات يوم إعادة هيكلة كل شيء.

## Solution

كغيرها من أنماط التصميم السلوكية، تعتمد **سلسلة المسؤوليات** على تحويل سلوكيات معينة إلى كائنات مستقلة تُسمى _معالجات_. في حالتنا، يجب استخراج كل عملية تحقق إلى فئتها الخاصة بطريقة واحدة تُنفّذ التحقق. يتم تمرير الطلب مع بياناته إلى هذه الطريقة كوسيط.

يقترح النمط ربط هذه المعالجات في سلسلة. يحتوي كل معالج مرتبط على حقل لتخزين مرجع إلى المعالج التالي في السلسلة. بالإضافة إلى معالجة الطلب، تُمرّر المعالجات الطلب على طول السلسلة. يتنقل الطلب على طول السلسلة حتى تحصل جميع المعالجات على فرصة لمعالجته.

Here’s the best part: a handler can decide not to pass the request further down the chain and effectively stop any further processing.

In our example with ordering systems, a handler performs the processing and then decides whether to pass the request further down the chain. Assuming the request contains the right data, all the handlers can execute their primary behavior, whether it’s authentication checks or caching.

تصطف المعالجات واحدة تلو الأخرى، مكوّنةً سلسلة.

However, there’s a slightly different approach (and it’s a bit more canonical) in which, upon receiving a request, a handler decides whether it can process it. If it can, it doesn’t pass the request any further. So it’s either only one handler that processes the request or none at all. This approach is very common when dealing with events in stacks of elements within a graphical user interface.

For instance, when a user clicks a button, the event propagates through the chain of GUI elements that starts with the button, goes along its containers (like forms or panels), and ends up with the main application window. The event is processed by the first element in the chain that’s capable of handling it. This example is also noteworthy because it shows that a chain can always be extracted from an object tree.

يمكن تكوين سلسلة من فرع في شجرة كائنات.

It’s crucial that all handler classes implement the same interface. Each concrete handler should only care about the following one having the `execute` method. This way you can compose chains at runtime, using various handlers without coupling your code to their concrete classes.

## Structure

1. يُعلن **المعالج** عن الواجهة المشتركة لجميع المعالجات المحددة. عادةً يحتوي على طريقة واحدة فقط لمعالجة الطلبات، لكن أحيانًا قد يحتوي أيضًا على طريقة أخرى لتعيين المعالج التالي في السلسلة.
2. The **Base Handler** is an optional class where you can put the boilerplate code that’s common to all handler classes.
عادةً تُعرّف هذه الفئة حقلًا لتخزين مرجع إلى المعالج التالي. يمكن للعملاء بناء سلسلة بتمرير معالج إلى مُنشئ أو مُحدِّد المعالج السابق. يمكن للفئة أيضًا تنفيذ سلوك المعالجة الافتراضي: يمكنها تمرير التنفيذ إلى المعالج التالي بعد التحقق من وجوده.
3. تحتوي **المعالجات المحددة** على الكود الفعلي لمعالجة الطلبات. عند استقبال طلب، يجب على كل معالج أن يقرر ما إذا كان سيعالجه، وبالإضافة إلى ذلك، ما إذا كان سيمرره على طول السلسلة.
عادةً ما تكون المعالجات مكتفية بذاتها وغير قابلة للتغيير، وتقبل جميع البيانات الضرورية مرة واحدة فقط عبر المُنشئ.
4. The **Client** may compose chains just once or compose them dynamically, depending on the application’s logic. Note that a request can be sent to any handler in the chain—it doesn’t have to be the first one.

## Pseudocode

في هذا المثال، يتولى نمط **سلسلة المسؤوليات** عرض معلومات المساعدة السياقية لعناصر واجهة المستخدم الرسومية النشطة.

تُبنى فئات واجهة المستخدم الرسومية باستخدام نمط المركّب. يرتبط كل عنصر بعنصر حاويه. في أي لحظة، يمكنك بناء سلسلة من العناصر تبدأ بالعنصر نفسه وتمر بجميع عناصر الحاوي.

The application’s GUI is usually structured as an object tree. For example, the `Dialog` class, which renders the main window of the app, would be the root of the object tree. The dialog contains `Panels`, which might contain other panels or simple low-level elements like `Buttons` and `TextFields`.

يمكن للمكون البسيط عرض تلميحات سياقية موجزة، طالما أن المكون لديه نص مساعدة مُعيَّن. لكن المكونات الأكثر تعقيدًا تُحدد طريقتها الخاصة لعرض المساعدة السياقية، كعرض مقتطف من الدليل أو فتح صفحة في المتصفح.

That’s how a help request traverses GUI objects.

When a user points the mouse cursor at an element and presses the `F1` key, the application detects the component under the pointer and sends it a help request. The request bubbles up through all the element’s containers until it reaches the element that’s capable of displaying the help information.

// تُعلن واجهة المعالج عن طريقة لتنفيذ
// طلب.
interface ComponentWithContextualHelp is
    method showHelp()

// الفئة الأساسية للمكونات البسيطة.
abstract class Component implements ComponentWithContextualHelp is
    field tooltipText: string

    // يعمل حاوي المكون كالرابط التالي في
    // سلسلة المعالجات.
    protected field container: Container

    // يعرض المكون تلميحًا إذا كان هناك نص مساعدة
    // مُعيَّن له. وإلا يُعيد توجيه الاستدعاء إلى
    // الحاوي، إن وُجد.
    method showHelp() is
        if (tooltipText != null)
            // عرض التلميح.
        else
            container.showHelp()

// يمكن للحاويات احتواء مكونات بسيطة وحاويات أخرى
// كعناصر أبناء. علاقات السلسلة مُنشأة هنا.
// ترث الفئة سلوك showHelp من
// أصلها.
abstract class Container extends Component is
    protected field children: array of Component

    method add(child) is
        children.add(child)
        child.container = this

// قد تكتفي المكونات الأولية بتنفيذ المساعدة الافتراضي...
class Button extends Component is
    // ...

// لكن يمكن للمكونات المعقدة تجاوز التنفيذ الافتراضي.
// إذا تعذّر توفير نص المساعدة بطريقة جديدة،
// يمكن للمكون دائمًا استدعاء التنفيذ الأساسي
// (راجع فئة Component).
class Panel extends Container is
    field modalHelpText: string

    method showHelp() is
        if (modalHelpText != null)
            // عرض نافذة منبثقة مع نص المساعدة.
        else
            super.showHelp()

// ...مثل ما سبق...
class Dialog extends Container is
    field wikiPageURL: string

    method showHelp() is
        if (wikiPageURL != null)
            // فتح صفحة مساعدة wiki.
        else
            super.showHelp()

// كود العميل.
class Application is
    // يُهيئ كل تطبيق السلسلة بطريقة مختلفة.
    method createUI() is
        dialog = new Dialog("Budget Reports")
        dialog.wikiPageURL = "http://..."
        panel = new Panel(0, 0, 400, 800)
        panel.modalHelpText = "This panel does..."
        ok = new Button(250, 760, 50, 20, "OK")
        ok.tooltipText = "This is an OK button that..."
        cancel = new Button(320, 760, 50, 20, "Cancel")
        // ...
        panel.add(ok)
        panel.add(cancel)
        dialog.add(panel)

    // تخيّل ما يحدث هنا.
    method onF1KeyPress() is
        component = this.getComponentAtMouseCoords()
        component.showHelp()

## Applicability

استخدم نمط سلسلة المسؤوليات عندما يُتوقَّع من برنامجك معالجة أنواع مختلفة من الطلبات بطرق متنوعة، لكن الأنواع الدقيقة للطلبات وتسلسلها غير معروفة مسبقًا.

 يتيح النمط ربط عدة معالجات في سلسلة واحدة، وعند استقبال طلب، "سؤال" كل معالج عمّا إذا كان بمقدوره معالجته. وبهذه الطريقة تحصل جميع المعالجات على فرصة لمعالجة الطلب.

 استخدم النمط عندما يكون من الضروري تنفيذ عدة معالجات بترتيب معين.

 نظرًا لأنك تستطيع ربط المعالجات في السلسلة بأي ترتيب، فإن جميع الطلبات ستمر عبر السلسلة تمامًا كما خططت.

 استخدم نمط CoR عندما يُفترض أن تتغير مجموعة المعالجات وترتيبها أثناء التشغيل.

 إذا وفّرت مُحدِّدات (setters) لحقل المرجع داخل فئات المعالجات، فستتمكن من إدراج المعالجات وإزالتها وإعادة ترتيبها ديناميكيًا.

## How to Implement

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

  * ما إذا كان سيعالج الطلب.
  * ما إذا كان سيمرر الطلب على طول السلسلة.
4. قد يجمع العميل السلاسل بنفسه أو يتلقاها مُجمَّعة مسبقًا من كائنات أخرى. في الحالة الأخيرة، يجب تنفيذ بعض فئات المصنع لبناء السلاسل وفق الإعدادات أو متطلبات البيئة.
5. يمكن للعميل تشغيل أي معالج في السلسلة، وليس فقط الأول. سيتم تمرير الطلب على طول السلسلة حتى يرفض أحد المعالجات تمريره أو حتى يصل إلى نهاية السلسلة.
6. بسبب الطبيعة الديناميكية للسلسلة، يجب أن يكون العميل مستعدًا للتعامل مع السيناريوهات التالية:

  * قد تتكون السلسلة من رابط واحد فقط.
  * قد لا تصل بعض الطلبات إلى نهاية السلسلة.
  * قد تصل طلبات أخرى إلى نهاية السلسلة دون معالجة.

## Pros

* يمكنك التحكم في ترتيب معالجة الطلبات.
* _مبدأ المسؤولية الواحدة_. يمكنك فصل الفئات التي تستدعي العمليات عن الفئات التي تنفذها.
* _مبدأ الفتح/الإغلاق_. يمكنك تقديم معالجات جديدة في التطبيق دون كسر كود العميل الحالي.

## Cons

* قد تنتهي بعض الطلبات دون معالجة.

## Relations with Other Patterns

* [سلسلة المسؤوليات](/ar/design-patterns/chain-of-responsibility), [الأمر](/ar/design-patterns/command), [الوسيط](/ar/design-patterns/mediator) and [المراقب](/ar/design-patterns/observer) تتناول طرقًا مختلفة لربط مُرسِلي الطلبات ومستقبليها:

  * _سلسلة المسؤوليات_ تُمرّر طلبًا بشكل تسلسلي عبر سلسلة ديناميكية من المستقبلين المحتملين حتى يعالجه أحدهم.
  * _الأمر_ يُنشئ اتصالات أحادية الاتجاه بين المُرسِلين والمستقبلين.
  * _الوسيط_ يُلغي الاتصالات المباشرة بين المُرسِلين والمستقبلين، مُجبرًا إياهم على التواصل بشكل غير مباشر عبر كائن وسيط.
  * _المراقب_ يتيح للمستقبلين الاشتراك وإلغاء الاشتراك ديناميكيًا من استقبال الطلبات.
* [سلسلة المسؤوليات](/ar/design-patterns/chain-of-responsibility) يُستخدم غالبًا بالتزامن مع [المركّب](/ar/design-patterns/composite). في هذه الحالة، عندما يحصل مكون ورقي على طلب، قد يمرره عبر سلسلة جميع المكونات الأصلية وصولًا إلى جذر شجرة الكائنات.
* يمكن تنفيذ المعالجات في [سلسلة المسؤوليات](/ar/design-patterns/chain-of-responsibility) يمكن تنفيذها كـ [الأوامر](/ar/design-patterns/command). في هذه الحالة، يمكنك تنفيذ الكثير من العمليات المختلفة على نفس كائن السياق، الذي يمثله طلب.
However, there’s another approach, where the request itself is a _Command_ object. In this case, you can execute the same operation in a series of different contexts linked into a chain.
* [سلسلة المسؤوليات](/ar/design-patterns/chain-of-responsibility) and [المزخرف](/ar/design-patterns/decorator) لديهما هياكل فئات متشابهة جدًا. يعتمد كلا النمطين على التركيب العودي لتمرير التنفيذ عبر سلسلة من الكائنات. ومع ذلك، توجد عدة اختلافات جوهرية.
The _CoR_ handlers can execute arbitrary operations independently of each other. They can also stop passing the request further at any point. On the other hand, various _Decorators_ can extend the object’s behavior while keeping it consistent with the base interface. In addition, decorators aren’t allowed to break the flow of the request.
## Relations

**Related patterns**

- [الأمر (Command)](/ar/design-patterns/command.md)
- [الوسيط](/ar/design-patterns/mediator.md)
- [المراقب](/ar/design-patterns/observer.md)
- [المركَّب](/ar/design-patterns/composite.md)
- [المُزَخرِف](/ar/design-patterns/decorator.md)

## Code Examples

### java

```java
package refactoring_guru.chain_of_responsibility.example.middleware;

/**
 * فئة الوسيط الأساسية.
 */
public abstract class Middleware {
    private Middleware next;

    /**
     * يبني سلاسل من كائنات الوسيط.
     */
    public static Middleware link(Middleware first, Middleware... chain) {
        Middleware head = first;
        for (Middleware nextInChain: chain) {
            head.next = nextInChain;
            head = nextInChain;
        }
        return first;
    }

    /**
     * ستُنفِّذ الفئات الفرعية هذه الطريقة مع عمليات تحقق محددة.
     */
    public abstract boolean check(String email, String password);

    /**
     * يُشغّل التحقق على الكائن التالي في السلسلة أو ينهي الاجتياز إذا
     * وصلنا إلى آخر كائن في السلسلة.
     */
    protected boolean checkNext(String email, String password) {
        if (next == null) {
            return true;
        }
        return next.check(email, password);
    }
}

package refactoring_guru.chain_of_responsibility.example.middleware;

/**
 * معالج محدد. يتحقق من وجود عدد كبير جدًا من طلبات تسجيل الدخول الفاشلة.
 */
public class ThrottlingMiddleware extends Middleware {
    private int requestPerMinute;
    private int request;
    private long currentTime;

    public ThrottlingMiddleware(int requestPerMinute) {
        this.requestPerMinute = requestPerMinute;
        this.currentTime = System.currentTimeMillis();
    }

    /**
     * يُرجى ملاحظة أن استدعاء checkNext() يمكن إدراجه في البداية
     * أو في نهاية هذه الطريقة.
     *
     * يتيح ذلك مرونة أكبر بكثير من حلقة بسيطة على جميع كائنات
     * الوسيط. مثلًا، يمكن لعنصر في السلسلة تغيير ترتيب
     * عمليات التحقق بتشغيل تحققه بعد جميع التحققات الأخرى.
     */
    public boolean check(String email, String password) {
        if (System.currentTimeMillis() > currentTime + 60_000) {
            request = 0;
            currentTime = System.currentTimeMillis();
        }

        request++;
        
        if (request > requestPerMinute) {
            System.out.println("Request limit exceeded!");
            Thread.currentThread().stop();
        }
        return checkNext(email, password);
    }
}

package refactoring_guru.chain_of_responsibility.example.middleware;

import refactoring_guru.chain_of_responsibility.example.server.Server;

/**
 * معالج محدد. يتحقق من وجود مستخدم بالبيانات المُعطاة.
 */
public class UserExistsMiddleware extends Middleware {
    private Server server;

    public UserExistsMiddleware(Server server) {
        this.server = server;
    }

    public boolean check(String email, String password) {
        if (!server.hasEmail(email)) {
            System.out.println("This email is not registered!");
            return false;
        }
        if (!server.isValidPassword(email, password)) {
            System.out.println("Wrong password!");
            return false;
        }
        return checkNext(email, password);
    }
}

package refactoring_guru.chain_of_responsibility.example.middleware;

/**
 * معالج محدد. يتحقق من دور المستخدم.
 */
public class RoleCheckMiddleware extends Middleware {
    public boolean check(String email, String password) {
        if (email.equals("admin@example.com")) {
            System.out.println("Hello, admin!");
            return true;
        }
        System.out.println("Hello, user!");
        return checkNext(email, password);
    }
}

package refactoring_guru.chain_of_responsibility.example.server;

import refactoring_guru.chain_of_responsibility.example.middleware.Middleware;

import java.util.HashMap;
import java.util.Map;

/**
 * فئة الخادم.
 */
public class Server {
    private Map<String, String> users = new HashMap<>();
    private Middleware middleware;

    /**
     * يُمرّر العميل سلسلة من الكائنات إلى الخادم. يُحسّن ذلك المرونة
     * ويجعل اختبار فئة الخادم أسهل.
     */
    public void setMiddleware(Middleware middleware) {
        this.middleware = middleware;
    }

    /**
     * يحصل الخادم على البريد الإلكتروني وكلمة المرور من العميل
     * ويُرسل طلب التفويض إلى السلسلة.
     */
    public boolean logIn(String email, String password) {
        if (middleware.check(email, password)) {
            System.out.println("Authorization have been successful!");

            // قم بتنفيذ شيء مفيد هنا للمستخدمين المصادَق عليهم.

            return true;
        }
        return false;
    }

    public void register(String email, String password) {
        users.put(email, password);
    }

    public boolean hasEmail(String email) {
        return users.containsKey(email);
    }

    public boolean isValidPassword(String email, String password) {
        return users.get(email).equals(password);
    }
}

package refactoring_guru.chain_of_responsibility.example;

import refactoring_guru.chain_of_responsibility.example.middleware.Middleware;
import refactoring_guru.chain_of_responsibility.example.middleware.RoleCheckMiddleware;
import refactoring_guru.chain_of_responsibility.example.middleware.ThrottlingMiddleware;
import refactoring_guru.chain_of_responsibility.example.middleware.UserExistsMiddleware;
import refactoring_guru.chain_of_responsibility.example.server.Server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * فئة العرض التوضيحي. يجتمع كل شيء هنا.
 */
public class Demo {
    private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    private static Server server;

    private static void init() {
        server = new Server();
        server.register("admin@example.com", "admin_pass");
        server.register("user@example.com", "user_pass");

        // جميع عمليات التحقق مترابطة. يمكن للعميل بناء سلاسل متنوعة باستخدام
        // نفس المكونات.
        Middleware middleware = Middleware.link(
            new ThrottlingMiddleware(2),
            new UserExistsMiddleware(server),
            new RoleCheckMiddleware()
        );

        // يحصل الخادم على السلسلة من كود العميل.
        server.setMiddleware(middleware);
    }

    public static void main(String[] args) throws IOException {
        init();

        boolean success;
        do {
            System.out.print("Enter email: ");
            String email = reader.readLine();
            System.out.print("Input password: ");
            String password = reader.readLine();
            success = server.logIn(email, password);
        } while (!success);
    }
}

Enter email: admin@example.com
Input password: admin_pass
Hello, admin!
Authorization have been successful!


Enter email: wrong@example.com
Input password: wrong_pass
This email is not registered!
Enter email: wrong@example.com
Input password: wrong_pass
This email is not registered!
Enter email: wrong@example.com
Input password: wrong_pass
Request limit exceeded!
```

### csharp

```csharp
using System;
using System.Collections.Generic;

namespace RefactoringGuru.DesignPatterns.ChainOfResponsibility.Conceptual
{
    // تُعلن واجهة IHandler عن طريقة لبناء سلسلة
    // المعالجات. كما تُعلن عن طريقة لتنفيذ طلب.
    public interface IHandler
    {
        IHandler SetNext(IHandler handler);
		
        object Handle(object request);
    }

    // يمكن تنفيذ سلوك التسلسل الافتراضي داخل فئة المعالج الأساسية.
    abstract class AbstractHandler : IHandler
    {
        private IHandler _nextHandler;

        public IHandler SetNext(IHandler handler)
        {
            this._nextHandler = handler;
            
            // إعادة معالج من هنا ستتيح لنا ربط المعالجات بطريقة
            // مناسبة كهذه:
            // monkey.SetNext(squirrel).SetNext(dog);
            return handler;
        }
		
        public virtual object Handle(object request)
        {
            if (this._nextHandler != null)
            {
                return this._nextHandler.Handle(request);
            }
            else
            {
                return null;
            }
        }
    }

    class MonkeyHandler : AbstractHandler
    {
        public override object Handle(object request)
        {
            if ((request as string) == "Banana")
            {
                return $"Monkey: I'll eat the {request.ToString()}.\n";
            }
            else
            {
                return base.Handle(request);
            }
        }
    }

    class SquirrelHandler : AbstractHandler
    {
        public override object Handle(object request)
        {
            if (request.ToString() == "Nut")
            {
                return $"Squirrel: I'll eat the {request.ToString()}.\n";
            }
            else
            {
                return base.Handle(request);
            }
        }
    }

    class DogHandler : AbstractHandler
    {
        public override object Handle(object request)
        {
            if (request.ToString() == "MeatBall")
            {
                return $"Dog: I'll eat the {request.ToString()}.\n";
            }
            else
            {
                return base.Handle(request);
            }
        }
    }

    class Client
    {
        // عادةً ما يكون كود العميل مُهيأً للعمل مع معالج واحد. في
        // معظم الحالات، لا يدرك حتى أن المعالج جزء من سلسلة.
        public static void ClientCode(AbstractHandler handler)
        {
            foreach (var food in new List<string> { "Nut", "Banana", "Cup of coffee" })
            {
                Console.WriteLine($"Client: Who wants a {food}?");

                var result = handler.Handle(food);

                if (result != null)
                {
                    Console.Write($"   {result}");
                }
                else
                {
                    Console.WriteLine($"   {food} was left untouched.");
                }
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // الجزء الآخر من كود العميل يبني السلسلة الفعلية.
            var monkey = new MonkeyHandler();
            var squirrel = new SquirrelHandler();
            var dog = new DogHandler();

            monkey.SetNext(squirrel).SetNext(dog);

            // يجب أن يتمكن العميل من إرسال طلب إلى أي معالج،
            // وليس فقط الأول في السلسلة.
            Console.WriteLine("Chain: Monkey > Squirrel > Dog\n");
            Client.ClientCode(monkey);
            Console.WriteLine();

            Console.WriteLine("Subchain: Squirrel > Dog\n");
            Client.ClientCode(squirrel);
        }
    }
}

Chain: Monkey > Squirrel > Dog

Client: Who wants a Nut?
   Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
   Monkey: I'll eat the Banana.
Client: Who wants a Cup of coffee?
   Cup of coffee was left untouched.

Subchain: Squirrel > Dog

Client: Who wants a Nut?
   Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
   Banana was left untouched.
Client: Who wants a Cup of coffee?
   Cup of coffee was left untouched.
```

### cpp

```cpp
/**
 * تُعلن واجهة المعالج عن طريقة لبناء سلسلة المعالجات.
 * كما تُعلن عن طريقة لتنفيذ طلب.
 */
class Handler {
 public:
  virtual Handler *SetNext(Handler *handler) = 0;
  virtual std::string Handle(std::string request) = 0;
};
/**
 * يمكن تنفيذ سلوك التسلسل الافتراضي داخل فئة المعالج الأساسية.
 */
class AbstractHandler : public Handler {
  /**
   * @var Handler
   */
 private:
  Handler *next_handler_;

 public:
  AbstractHandler() : next_handler_(nullptr) {
  }
  Handler *SetNext(Handler *handler) override {
    this->next_handler_ = handler;
    // Returning a handler from here will let us link handlers in a convenient
    // way like this:
    // $monkey->setNext($squirrel)->setNext($dog);
    return handler;
  }
  std::string Handle(std::string request) override {
    if (this->next_handler_) {
      return this->next_handler_->Handle(request);
    }

    return {};
  }
};
/**
 * تعالج جميع المعالجات المحددة الطلب أو تمرره إلى المعالج التالي
 * في السلسلة.
 */
class MonkeyHandler : public AbstractHandler {
 public:
  std::string Handle(std::string request) override {
    if (request == "Banana") {
      return "Monkey: I'll eat the " + request + ".\n";
    } else {
      return AbstractHandler::Handle(request);
    }
  }
};
class SquirrelHandler : public AbstractHandler {
 public:
  std::string Handle(std::string request) override {
    if (request == "Nut") {
      return "Squirrel: I'll eat the " + request + ".\n";
    } else {
      return AbstractHandler::Handle(request);
    }
  }
};
class DogHandler : public AbstractHandler {
 public:
  std::string Handle(std::string request) override {
    if (request == "MeatBall") {
      return "Dog: I'll eat the " + request + ".\n";
    } else {
      return AbstractHandler::Handle(request);
    }
  }
};
/**
 * عادةً ما يكون كود العميل مُهيأً للعمل مع معالج واحد. في معظم
 * الحالات، لا يدرك حتى أن المعالج جزء من سلسلة.
 */
void ClientCode(Handler &handler) {
  std::vector<std::string> food = {"Nut", "Banana", "Cup of coffee"};
  for (const std::string &f : food) {
    std::cout << "Client: Who wants a " << f << "?\n";
    const std::string result = handler.Handle(f);
    if (!result.empty()) {
      std::cout << "  " << result;
    } else {
      std::cout << "  " << f << " was left untouched.\n";
    }
  }
}
/**
 * الجزء الآخر من كود العميل يبني السلسلة الفعلية.
 */
int main() {
  MonkeyHandler *monkey = new MonkeyHandler;
  SquirrelHandler *squirrel = new SquirrelHandler;
  DogHandler *dog = new DogHandler;
  monkey->SetNext(squirrel)->SetNext(dog);

  /**
   * يجب أن يتمكن العميل من إرسال طلب إلى أي معالج،
   * وليس فقط الأول في السلسلة.
   */
  std::cout << "Chain: Monkey > Squirrel > Dog\n\n";
  ClientCode(*monkey);
  std::cout << "\n";
  std::cout << "Subchain: Squirrel > Dog\n\n";
  ClientCode(*squirrel);

  delete monkey;
  delete squirrel;
  delete dog;

  return 0;
}

Chain: Monkey > Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
  Monkey: I'll eat the Banana.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.

Subchain: Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
  Banana was left untouched.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.
```

### go

```go
package main

type Department interface {
	execute(*Patient)
	setNext(Department)
}

package main

import "fmt"

type Reception struct {
	next Department
}

func (r *Reception) execute(p *Patient) {
	if p.registrationDone {
		fmt.Println("Patient registration already done")
		r.next.execute(p)
		return
	}
	fmt.Println("Reception registering patient")
	p.registrationDone = true
	r.next.execute(p)
}

func (r *Reception) setNext(next Department) {
	r.next = next
}

package main

import "fmt"

type Doctor struct {
	next Department
}

func (d *Doctor) execute(p *Patient) {
	if p.doctorCheckUpDone {
		fmt.Println("Doctor checkup already done")
		d.next.execute(p)
		return
	}
	fmt.Println("Doctor checking patient")
	p.doctorCheckUpDone = true
	d.next.execute(p)
}

func (d *Doctor) setNext(next Department) {
	d.next = next
}

package main

import "fmt"

type Medical struct {
	next Department
}

func (m *Medical) execute(p *Patient) {
	if p.medicineDone {
		fmt.Println("Medicine already given to patient")
		m.next.execute(p)
		return
	}
	fmt.Println("Medical giving medicine to patient")
	p.medicineDone = true
	m.next.execute(p)
}

func (m *Medical) setNext(next Department) {
	m.next = next
}

package main

import "fmt"

type Cashier struct {
	next Department
}

func (c *Cashier) execute(p *Patient) {
	if p.paymentDone {
		fmt.Println("Payment Done")
	}
	fmt.Println("Cashier getting money from patient patient")
}

func (c *Cashier) setNext(next Department) {
	c.next = next
}

package main

type Patient struct {
	name              string
	registrationDone  bool
	doctorCheckUpDone bool
	medicineDone      bool
	paymentDone       bool
}

package main

func main() {

	cashier := &Cashier{}

	//تعيين التالي لقسم الطب
	medical := &Medical{}
	medical.setNext(cashier)

	//تعيين التالي لقسم الطبيب
	doctor := &Doctor{}
	doctor.setNext(medical)

	//تعيين التالي لقسم الاستقبال
	reception := &Reception{}
	reception.setNext(doctor)

	patient := &Patient{name: "abc"}
	//زيارة المريض
	reception.execute(patient)
}

Reception registering patient
Doctor checking patient
Medical giving medicine to patient
Cashier getting money from patient patient
```

### php

```php
<?php

namespace RefactoringGuru\ChainOfResponsibility\Conceptual;

/**
 * تُعلن واجهة المعالج عن طريقة لبناء سلسلة المعالجات.
 * كما تُعلن عن طريقة لتنفيذ طلب.
 */
interface Handler
{
    public function setNext(Handler $handler): Handler;

    public function handle(string $request): ?string;
}

/**
 * يمكن تنفيذ سلوك التسلسل الافتراضي داخل فئة المعالج الأساسية.
 */
abstract class AbstractHandler implements Handler
{
    /**
     * @var Handler
     */
    private $nextHandler;

    public function setNext(Handler $handler): Handler
    {
        $this->nextHandler = $handler;
        // Returning a handler from here will let us link handlers in a
        // convenient way like this:
        // $monkey->setNext($squirrel)->setNext($dog);
        return $handler;
    }

    public function handle(string $request): ?string
    {
        if ($this->nextHandler) {
            return $this->nextHandler->handle($request);
        }

        return null;
    }
}

/**
 * تعالج جميع المعالجات المحددة الطلب أو تمرره إلى المعالج التالي
 * في السلسلة.
 */
class MonkeyHandler extends AbstractHandler
{
    public function handle(string $request): ?string
    {
        if ($request === "Banana") {
            return "Monkey: I'll eat the " . $request . ".\n";
        } else {
            return parent::handle($request);
        }
    }
}

class SquirrelHandler extends AbstractHandler
{
    public function handle(string $request): ?string
    {
        if ($request === "Nut") {
            return "Squirrel: I'll eat the " . $request . ".\n";
        } else {
            return parent::handle($request);
        }
    }
}

class DogHandler extends AbstractHandler
{
    public function handle(string $request): ?string
    {
        if ($request === "MeatBall") {
            return "Dog: I'll eat the " . $request . ".\n";
        } else {
            return parent::handle($request);
        }
    }
}

/**
 * عادةً ما يكون كود العميل مُهيأً للعمل مع معالج واحد. في معظم
 * الحالات، لا يدرك حتى أن المعالج جزء من سلسلة.
 */
function clientCode(Handler $handler)
{
    foreach (["Nut", "Banana", "Cup of coffee"] as $food) {
        echo "Client: Who wants a " . $food . "?\n";
        $result = $handler->handle($food);
        if ($result) {
            echo "  " . $result;
        } else {
            echo "  " . $food . " was left untouched.\n";
        }
    }
}

/**
 * الجزء الآخر من كود العميل يبني السلسلة الفعلية.
 */
$monkey = new MonkeyHandler();
$squirrel = new SquirrelHandler();
$dog = new DogHandler();

$monkey->setNext($squirrel)->setNext($dog);

/**
 * يجب أن يتمكن العميل من إرسال طلب إلى أي معالج، وليس فقط
 * الأول في السلسلة.
 */
echo "Chain: Monkey > Squirrel > Dog\n\n";
clientCode($monkey);
echo "\n";

echo "Subchain: Squirrel > Dog\n\n";
clientCode($squirrel);

Chain: Monkey > Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
  Monkey: I'll eat the Banana.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.

Subchain: Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
  Banana was left untouched.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.

<?php

namespace RefactoringGuru\ChainOfResponsibility\RealWorld;

/**
 * يُعلن نمط CoR الكلاسيكي عن دور واحد للكائنات التي تكوّن السلسلة،
 * وهو المعالج. في مثالنا، دعنا نُفرّق بين الوسيط والمعالج
 * النهائي للتطبيق، الذي يُنفَّذ عندما يمر الطلب عبر جميع كائنات الوسيط.
 *
 * تُعلن فئة Middleware الأساسية عن واجهة لربط كائنات
 * الوسيط في سلسلة.
 */
abstract class Middleware
{
    /**
     * @var Middleware
     */
    private $next;

    /**
     * يمكن استخدام هذه الطريقة لبناء سلسلة من كائنات الوسيط.
     */
    public function linkWith(Middleware $next): Middleware
    {
        $this->next = $next;

        return $next;
    }

    /**
     * يجب على الفئات الفرعية تجاوز هذه الطريقة لتوفير عمليات تحققها الخاصة.
     * يمكن للفئة الفرعية الرجوع إلى التنفيذ الأصل إذا لم تستطع معالجة طلب.
     */
    public function check(string $email, string $password): bool
    {
        if (!$this->next) {
            return true;
        }

        return $this->next->check($email, $password);
    }
}

/**
 * يتحقق هذا الوسيط المحدد من وجود مستخدم بالبيانات المُعطاة.
 */
class UserExistsMiddleware extends Middleware
{
    private $server;

    public function __construct(Server $server)
    {
        $this->server = $server;
    }

    public function check(string $email, string $password): bool
    {
        if (!$this->server->hasEmail($email)) {
            echo "UserExistsMiddleware: This email is not registered!\n";

            return false;
        }

        if (!$this->server->isValidPassword($email, $password)) {
            echo "UserExistsMiddleware: Wrong password!\n";

            return false;
        }

        return parent::check($email, $password);
    }
}

/**
 * يتحقق هذا الوسيط المحدد من امتلاك المستخدم المرتبط بالطلب صلاحيات كافية.
 */
class RoleCheckMiddleware extends Middleware
{
    public function check(string $email, string $password): bool
    {
        if ($email === "admin@example.com") {
            echo "RoleCheckMiddleware: Hello, admin!\n";

            return true;
        }
        echo "RoleCheckMiddleware: Hello, user!\n";

        return parent::check($email, $password);
    }
}

/**
 * يتحقق هذا الوسيط المحدد من وجود عدد كبير جدًا من طلبات تسجيل الدخول الفاشلة.
 */
class ThrottlingMiddleware extends Middleware
{
    private $requestPerMinute;

    private $request;

    private $currentTime;

    public function __construct(int $requestPerMinute)
    {
        $this->requestPerMinute = $requestPerMinute;
        $this->currentTime = time();
    }

    /**
     * يُرجى ملاحظة أن استدعاء parent::check يمكن إدراجه في البداية
     * أو في نهاية هذه الطريقة.
     *
     * يتيح ذلك مرونة أكبر بكثير من حلقة بسيطة على جميع كائنات
     * الوسيط. مثلًا، يمكن للوسيط تغيير ترتيب عمليات التحقق
     * بتشغيل تحققه بعد الجميع.
     */
    public function check(string $email, string $password): bool
    {
        if (time() > $this->currentTime + 60) {
            $this->request = 0;
            $this->currentTime = time();
        }

        $this->request++;

        if ($this->request > $this->requestPerMinute) {
            echo "ThrottlingMiddleware: Request limit exceeded!\n";
            die();
        }

        return parent::check($email, $password);
    }
}

/**
 * هذه فئة التطبيق التي تعمل كمعالج حقيقي. تستخدم فئة Server
 * نمط CoR لتنفيذ مجموعة من وسطاء المصادقة المختلفة قبل
 * تشغيل منطق الأعمال المرتبط بطلب.
 */
class Server
{
    private $users = [];

    /**
     * @var Middleware
     */
    private $middleware;

    /**
     * يمكن للعميل تهيئة الخادم بسلسلة من كائنات الوسيط.
     */
    public function setMiddleware(Middleware $middleware): void
    {
        $this->middleware = $middleware;
    }

    /**
     * يحصل الخادم على البريد الإلكتروني وكلمة المرور من العميل
     * ويُرسل طلب التفويض إلى الوسيط.
     */
    public function logIn(string $email, string $password): bool
    {
        if ($this->middleware->check($email, $password)) {
            echo "Server: Authorization has been successful!\n";

            // قم بتنفيذ شيء مفيد للمستخدمين المصادَق عليهم.

            return true;
        }

        return false;
    }

    public function register(string $email, string $password): void
    {
        $this->users[$email] = $password;
    }

    public function hasEmail(string $email): bool
    {
        return isset($this->users[$email]);
    }

    public function isValidPassword(string $email, string $password): bool
    {
        return $this->users[$email] === $password;
    }
}

/**
 * كود العميل.
 */
$server = new Server();
$server->register("admin@example.com", "admin_pass");
$server->register("user@example.com", "user_pass");

// جميع وسطاء الطلبات مترابطون. يمكن للعميل بناء تهيئات مختلفة
// للسلاسل حسب احتياجاته.
$middleware = new ThrottlingMiddleware(2);
$middleware
    ->linkWith(new UserExistsMiddleware($server))
    ->linkWith(new RoleCheckMiddleware());

// يحصل الخادم على السلسلة من كود العميل.
$server->setMiddleware($middleware);

// ...

do {
    echo "\nEnter your email:\n";
    $email = readline();
    echo "Enter your password:\n";
    $password = readline();
    $success = $server->logIn($email, $password);
} while (!$success);

Enter your email:
asd
Enter your password:
123
UserExistsMiddleware: This email is not registered!

Enter your email:
admin@example.com
Enter your password:
wrong
UserExistsMiddleware: Wrong password!

Enter your email:
admin@example.com
Enter your password:
letmein
ThrottlingMiddleware: Request limit exceeded!



Enter your email:
admin@example.com
Enter your password:
admin_pass
RoleCheckMiddleware: Hello, admin!
Server: Authorization has been successful!
```

### python

```python
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any, Optional


class Handler(ABC):
    """
    تُعلن واجهة المعالج عن طريقة لبناء سلسلة المعالجات.
    كما تُعلن عن طريقة لتنفيذ طلب.
    """

    @abstractmethod
    def set_next(self, handler: Handler) -> Handler:
        pass

    @abstractmethod
    def handle(self, request) -> Optional[str]:
        pass


class AbstractHandler(Handler):
    """
    يمكن تنفيذ سلوك التسلسل الافتراضي داخل فئة المعالج
    الأساسية.
    """

    _next_handler: Handler = None

    def set_next(self, handler: Handler) -> Handler:
        self._next_handler = handler
        # إعادة معالج من هنا ستتيح لنا ربط المعالجات بطريقة
        # مناسبة كهذه:
        # monkey.set_next(squirrel).set_next(dog)
        return handler

    @abstractmethod
    def handle(self, request: Any) -> str:
        if self._next_handler:
            return self._next_handler.handle(request)

        return None


"""
تعالج جميع المعالجات المحددة الطلب أو تمرره إلى المعالج التالي في
السلسلة.
"""


class MonkeyHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "Banana":
            return f"Monkey: I'll eat the {request}"
        else:
            return super().handle(request)


class SquirrelHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "Nut":
            return f"Squirrel: I'll eat the {request}"
        else:
            return super().handle(request)


class DogHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "MeatBall":
            return f"Dog: I'll eat the {request}"
        else:
            return super().handle(request)


def client_code(handler: Handler) -> None:
    """
    عادةً ما يكون كود العميل مُهيأً للعمل مع معالج واحد. في معظم
    الحالات، لا يدرك حتى أن المعالج جزء من سلسلة.
    """

    for food in ["Nut", "Banana", "Cup of coffee"]:
        print(f"\nClient: Who wants a {food}?")
        result = handler.handle(food)
        if result:
            print(f"  {result}", end="")
        else:
            print(f"  {food} was left untouched.", end="")


if __name__ == "__main__":
    monkey = MonkeyHandler()
    squirrel = SquirrelHandler()
    dog = DogHandler()

    monkey.set_next(squirrel).set_next(dog)

    # يجب أن يتمكن العميل من إرسال طلب إلى أي معالج، وليس فقط
    # الأول في السلسلة.
    print("Chain: Monkey > Squirrel > Dog")
    client_code(monkey)
    print("\n")

    print("Subchain: Squirrel > Dog")
    client_code(squirrel)

Chain: Monkey > Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut
Client: Who wants a Banana?
  Monkey: I'll eat the Banana
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.

Subchain: Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut
Client: Who wants a Banana?
  Banana was left untouched.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.
```

### ruby

```ruby
# تُعلن واجهة المعالج عن طريقة لبناء سلسلة المعالجات. كما
# تُعلن عن طريقة لتنفيذ طلب.
class Handler
  # @abstract
  #
  # @param [Handler] handler
  def next_handler=(handler)
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end

  # @abstract
  #
  # @param [String] request
  #
  # @return [String, nil]
  def handle(request)
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

# يمكن تنفيذ سلوك التسلسل الافتراضي داخل فئة المعالج الأساسية.
class AbstractHandler < Handler
  # @return [Handler]
  attr_writer :next_handler

  # @param [Handler] handler
  #
  # @return [Handler]
  def next_handler(handler)
    @next_handler = handler
    # Returning a handler from here will let us link handlers in a convenient
    # way like this:
    # monkey.next_handler(squirrel).next_handler(dog)
    handler
  end

  # @abstract
  #
  # @param [String] request
  #
  # @return [String, nil]
  def handle(request)
    return @next_handler.handle(request) if @next_handler

    nil
  end
end

# تعالج جميع المعالجات المحددة الطلب أو تمرره إلى المعالج التالي
# في السلسلة.
class MonkeyHandler < AbstractHandler
  # @param [String] request
  #
  # @return [String, nil]
  def handle(request)
    if request == 'Banana'
      "Monkey: I'll eat the #{request}"
    else
      super(request)
    end
  end
end

class SquirrelHandler < AbstractHandler
  # @param [String] request
  #
  # @return [String, nil]
  def handle(request)
    if request == 'Nut'
      "Squirrel: I'll eat the #{request}"
    else
      super(request)
    end
  end
end

class DogHandler < AbstractHandler
  # @param [String] request
  #
  # @return [String, nil]
  def handle(request)
    if request == 'MeatBall'
      "Dog: I'll eat the #{request}"
    else
      super(request)
    end
  end
end

# عادةً ما يكون كود العميل مُهيأً للعمل مع معالج واحد. في معظم
# الحالات، لا يدرك حتى أن المعالج جزء من سلسلة.
def client_code(handler)
  ['Nut', 'Banana', 'Cup of coffee'].each do |food|
    puts "\nClient: Who wants a #{food}?"
    result = handler.handle(food)
    if result
      print "  #{result}"
    else
      print "  #{food} was left untouched."
    end
  end
end

monkey = MonkeyHandler.new
squirrel = SquirrelHandler.new
dog = DogHandler.new

monkey.next_handler(squirrel).next_handler(dog)

# يجب أن يتمكن العميل من إرسال طلب إلى أي معالج، وليس
# فقط الأول في السلسلة.
puts 'Chain: Monkey > Squirrel > Dog'
client_code(monkey)
puts "\n\n"

puts 'Subchain: Squirrel > Dog'
client_code(squirrel)

Chain: Monkey > Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut
Client: Who wants a Banana?
  Monkey: I'll eat the Banana
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.

Subchain: Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut
Client: Who wants a Banana?
  Banana was left untouched.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.
```

### rust

```rust
Patient -> Reception -> Doctor -> Medical -> Cashier

let mut reception = Reception::<Doctor::<Medical::<Cashier>>>::new(doctor); // 😱

let mut reception = Reception::new(doctor); // 👍

let mut reception = Reception::new(cashier); // 🕵️‍♀️

#[derive(Default)]
pub struct Patient {
    pub name: String,
    pub registration_done: bool,
    pub doctor_check_up_done: bool,
    pub medicine_done: bool,
    pub payment_done: bool,
}

mod cashier;
mod doctor;
mod medical;
mod reception;

pub use cashier::Cashier;
pub use doctor::Doctor;
pub use medical::Medical;
pub use reception::Reception;

use crate::patient::Patient;

/// دور واحد للكائنات التي تكوّن السلسلة.
/// يجب أن يحتوي تنفيذ الـ trait النموذجي على طريقتَي `handle` و`next`،
/// بينما يُنفَّذ `execute` افتراضيًا ويحتوي على منطق التسلسل الصحيح.
pub trait Department {
    fn execute(&mut self, patient: &mut Patient) {
        self.handle(patient);

        if let Some(next) = &mut self.next() {
            next.execute(patient);
        }
    }

    fn handle(&mut self, patient: &mut Patient);
    fn next(&mut self) -> &mut Option<Box<dyn Department>>;
}

/// يساعد في تغليف كائن في نوع boxed.
pub fn into_next(department: impl Department + Sized + 'static) -> Option<Box<dyn Department>> {
    Some(Box::new(department))
}

use super::{Department, Patient};

#[derive(Default)]
pub struct Cashier {
    next: Option<Box<dyn Department>>,
}

impl Department for Cashier {
    fn handle(&mut self, patient: &mut Patient) {
        if patient.payment_done {
            println!("Payment done");
        } else {
            println!("Cashier getting money from a patient {}", patient.name);
            patient.payment_done = true;
        }
    }

    fn next(&mut self) -> &mut Option<Box<dyn Department>> {
        &mut self.next
    }
}

use super::{into_next, Department, Patient};

pub struct Doctor {
    next: Option<Box<dyn Department>>,
}

impl Doctor {
    pub fn new(next: impl Department + 'static) -> Self {
        Self {
            next: into_next(next),
        }
    }
}

impl Department for Doctor {
    fn handle(&mut self, patient: &mut Patient) {
        if patient.doctor_check_up_done {
            println!("A doctor checkup is already done");
        } else {
            println!("Doctor checking a patient {}", patient.name);
            patient.doctor_check_up_done = true;
        }
    }

    fn next(&mut self) -> &mut Option<Box<dyn Department>> {
        &mut self.next
    }
}

use super::{into_next, Department, Patient};

pub struct Medical {
    next: Option<Box<dyn Department>>,
}

impl Medical {
    pub fn new(next: impl Department + 'static) -> Self {
        Self {
            next: into_next(next),
        }
    }
}

impl Department for Medical {
    fn handle(&mut self, patient: &mut Patient) {
        if patient.medicine_done {
            println!("Medicine is already given to a patient");
        } else {
            println!("Medical giving medicine to a patient {}", patient.name);
            patient.medicine_done = true;
        }
    }

    fn next(&mut self) -> &mut Option<Box<dyn Department>> {
        &mut self.next
    }
}

use super::{into_next, Department, Patient};

#[derive(Default)]
pub struct Reception {
    next: Option<Box<dyn Department>>,
}

impl Reception {
    pub fn new(next: impl Department + 'static) -> Self {
        Self {
            next: into_next(next),
        }
    }
}

impl Department for Reception {
    fn handle(&mut self, patient: &mut Patient) {
        if patient.registration_done {
            println!("Patient registration is already done");
        } else {
            println!("Reception registering a patient {}", patient.name);
            patient.registration_done = true;
        }
    }

    fn next(&mut self) -> &mut Option<Box<dyn Department>> {
        &mut self.next
    }
}

mod department;
mod patient;

use department::{Cashier, Department, Doctor, Medical, Reception};
use patient::Patient;

fn main() {
    let cashier = Cashier::default();
    let medical = Medical::new(cashier);
    let doctor = Doctor::new(medical);
    let mut reception = Reception::new(doctor);

    let mut patient = Patient {
        name: "John".into(),
        ..Patient::default()
    };

    // Reception handles a patient passing him to the next link in the chain.
    // Reception -> Doctor -> Medical -> Cashier.
    reception.execute(&mut patient);

    println!("\nThe patient has been already handled:\n");

    reception.execute(&mut patient);
}

Reception registering a patient John
Doctor checking a patient John
Medical giving medicine to a patient John
Cashier getting money from a patient John

The patient has been already handled:

Patient registration is already done
A doctor checkup is already done
Medicine is already given to a patient
Payment done
```

### swift

```swift
import XCTest

/// تُعلن واجهة المعالج عن طريقة لبناء سلسلة المعالجات.
/// كما تُعلن عن طريقة لتنفيذ طلب.
protocol Handler: AnyObject {

    @discardableResult
    func setNext(handler: Handler) -> Handler

    func handle(request: String) -> String?

    var nextHandler: Handler? { get set }
}

extension Handler {

    func setNext(handler: Handler) -> Handler {
        self.nextHandler = handler

        /// إعادة معالج من هنا ستتيح لنا ربط المعالجات بطريقة
        /// مناسبة كهذه:
        /// monkey.setNext(handler: squirrel).setNext(handler: dog)
        return handler
    }

    func handle(request: String) -> String? {
        return nextHandler?.handle(request: request)
    }
}

/// تعالج جميع المعالجات المحددة الطلب أو تمرره إلى المعالج التالي
/// في السلسلة.
class MonkeyHandler: Handler {

    var nextHandler: Handler?

    func handle(request: String) -> String? {
        if (request == "Banana") {
            return "Monkey: I'll eat the " + request + ".\n"
        } else {
            return nextHandler?.handle(request: request)
        }
    }
}

class SquirrelHandler: Handler {

    var nextHandler: Handler?

    func handle(request: String) -> String? {

        if (request == "Nut") {
            return "Squirrel: I'll eat the " + request + ".\n"
        } else {
            return nextHandler?.handle(request: request)
        }
    }
}

class DogHandler: Handler {

    var nextHandler: Handler?

    func handle(request: String) -> String? {
        if (request == "MeatBall") {
            return "Dog: I'll eat the " + request + ".\n"
        } else {
            return nextHandler?.handle(request: request)
        }
    }
}

/// عادةً ما يكون كود العميل مُهيأً للعمل مع معالج واحد. في معظم
/// الحالات، لا يدرك حتى أن المعالج جزء من سلسلة.
class Client {
    // ...
    static func someClientCode(handler: Handler) {

        let food = ["Nut", "Banana", "Cup of coffee"]

        for item in food {

            print("Client: Who wants a " + item + "?\n")

            guard let result = handler.handle(request: item) else {
                print("  " + item + " was left untouched.\n")
                return
            }

            print("  " + result)
        }
    }
    // ...
}

/// Let's see how it all works together.
class ChainOfResponsibilityConceptual: XCTestCase {
 
    func test() {

        /// الجزء الآخر من كود العميل يبني السلسلة الفعلية.

        let monkey = MonkeyHandler()
        let squirrel = SquirrelHandler()
        let dog = DogHandler()
        monkey.setNext(handler: squirrel).setNext(handler: dog)

        /// يجب أن يتمكن العميل من إرسال طلب إلى أي معالج، وليس فقط
        /// الأول في السلسلة.

        print("Chain: Monkey > Squirrel > Dog\n\n")
        Client.someClientCode(handler: monkey)
        print()
        print("Subchain: Squirrel > Dog\n\n")
        Client.someClientCode(handler: squirrel)
    }
}

Chain: Monkey > Squirrel > Dog


Client: Who wants a Nut?

Squirrel: I'll eat the Nut.

Client: Who wants a Banana?

Monkey: I'll eat the Banana.

Client: Who wants a Cup of coffee?

Cup of coffee was left untouched.


Subchain: Squirrel > Dog


Client: Who wants a Nut?

Squirrel: I'll eat the Nut.

Client: Who wants a Banana?

Banana was left untouched.

import Foundation
import UIKit
import XCTest


protocol Handler {

    var next: Handler? { get }

    func handle(_ request: Request) -> LocalizedError?
}

class BaseHandler: Handler {

    var next: Handler?

    init(with handler: Handler? = nil) {
        self.next = handler
    }

    func handle(_ request: Request) -> LocalizedError? {
        return next?.handle(request)
    }
}

class LoginHandler: BaseHandler {

    override func handle(_ request: Request) -> LocalizedError? {

        guard request.email?.isEmpty == false else {
            return AuthError.emptyEmail
        }

        guard request.password?.isEmpty == false else {
            return AuthError.emptyPassword
        }

        return next?.handle(request)
    }
}

class SignUpHandler: BaseHandler {

    private struct Limit {
        static let passwordLength = 8
    }

    override func handle(_ request: Request) -> LocalizedError? {

        guard request.email?.contains("@") == true else {
            return AuthError.invalidEmail
        }

        guard (request.password?.count ?? 0) >= Limit.passwordLength else {
            return AuthError.invalidPassword
        }

        guard request.password == request.repeatedPassword else {
            return AuthError.differentPasswords
        }

        return next?.handle(request)
    }
}

class LocationHandler: BaseHandler {

    override func handle(_ request: Request) -> LocalizedError? {
        guard isLocationEnabled() else {
            return AuthError.locationDisabled
        }
        return next?.handle(request)
    }

    func isLocationEnabled() -> Bool {
        return true /// يستدعي طريقة خاصة
    }
}

class NotificationHandler: BaseHandler {

    override func handle(_ request: Request) -> LocalizedError? {
        guard isNotificationsEnabled() else {
            return AuthError.notificationsDisabled
        }
        return next?.handle(request)
    }

    func isNotificationsEnabled() -> Bool {
        return false /// يستدعي طريقة خاصة
    }
}

enum AuthError: LocalizedError {

    case emptyFirstName
    case emptyLastName

    case emptyEmail
    case emptyPassword

    case invalidEmail
    case invalidPassword
    case differentPasswords

    case locationDisabled
    case notificationsDisabled

    var errorDescription: String? {
        switch self {
        case .emptyFirstName:
            return "First name is empty"
        case .emptyLastName:
            return "Last name is empty"
        case .emptyEmail:
            return "Email is empty"
        case .emptyPassword:
            return "Password is empty"
        case .invalidEmail:
            return "Email is invalid"
        case .invalidPassword:
            return "Password is invalid"
        case .differentPasswords:
            return "Password and repeated password should be equal"
        case .locationDisabled:
            return "Please turn location services on"
        case .notificationsDisabled:
            return "Please turn notifications on"
        }
    }
}


protocol Request {

    var firstName: String? { get }
    var lastName: String? { get }

    var email: String? { get }
    var password: String? { get }
    var repeatedPassword: String? { get }
}

extension Request {

    /// Default implementations

    var firstName: String? { return nil }
    var lastName: String? { return nil }

    var email: String? { return nil }
    var password: String? { return nil }
    var repeatedPassword: String? { return nil }
}

struct SignUpRequest: Request {

    var firstName: String?
    var lastName: String?

    var email: String?
    var password: String?
    var repeatedPassword: String?
}

struct LoginRequest: Request {

    var email: String?
    var password: String?
}



protocol AuthHandlerSupportable: AnyObject {

    var handler: Handler? { get set }
}

class BaseAuthViewController: UIViewController, AuthHandlerSupportable {

    /// Base class or extensions can be used to implement a base behavior
    var handler: Handler?

    init(handler: Handler) {
        self.handler = handler
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

class LoginViewController: BaseAuthViewController {

    func loginButtonSelected() {
        print("Login View Controller: User selected Login button")

        let request = LoginRequest(email: "smth@gmail.com", password: "123HardPass")

        if let error = handler?.handle(request) {
            print("Login View Controller: something went wrong")
            print("Login View Controller: Error -> " + (error.errorDescription ?? ""))
        } else {
            print("Login View Controller: Preconditions are successfully validated")
        }
    }
}

class SignUpViewController: BaseAuthViewController {

    func signUpButtonSelected() {
        print("SignUp View Controller: User selected SignUp button")

        let request = SignUpRequest(firstName: "Vasya",
                                    lastName: "Pupkin",
                                    email: "vasya.pupkin@gmail.com",
                                    password: "123HardPass",
                                    repeatedPassword: "123HardPass")

        if let error = handler?.handle(request) {
            print("SignUp View Controller: something went wrong")
            print("SignUp View Controller: Error -> " + (error.errorDescription ?? ""))
        } else {
            print("SignUp View Controller: Preconditions are successfully validated")
        }
    }
}



class ChainOfResponsibilityRealWorld: XCTestCase {

    func testChainOfResponsibilityRealWorld() {

        print("Client: Let's test Login flow!")

        let loginHandler = LoginHandler(with: LocationHandler())
        let loginController = LoginViewController(handler: loginHandler)

        loginController.loginButtonSelected()

        print("\nClient: Let's test SignUp flow!")

        let signUpHandler = SignUpHandler(with: LocationHandler(with: NotificationHandler()))
        let signUpController = SignUpViewController(handler: signUpHandler)

        signUpController.signUpButtonSelected()
    }
}

Client: Let's test Login flow!
Login View Controller: User selected Login button
Login View Controller: Preconditions are successfully validated

Client: Let's test SignUp flow!
SignUp View Controller: User selected SignUp button
SignUp View Controller: something went wrong
SignUp View Controller: Error -> Please turn notifications on
```

### typescript

```typescript
/**
 * تُعلن واجهة المعالج عن طريقة لبناء سلسلة المعالجات.
 * كما تُعلن عن طريقة لتنفيذ طلب.
 */
interface Handler<Request = string, Result = string> {
    setNext(handler: Handler<Request, Result>): Handler<Request, Result>;

    handle(request: Request): Result;
}

/**
 * يمكن تنفيذ سلوك التسلسل الافتراضي داخل فئة المعالج الأساسية.
 */
abstract class AbstractHandler implements Handler
{
    private nextHandler: Handler;

    public setNext(handler: Handler): Handler {
        this.nextHandler = handler;
        // إعادة معالج من هنا ستتيح لنا ربط المعالجات بطريقة
        // مناسبة كهذه:
        // monkey.setNext(squirrel).setNext(dog);
        return handler;
    }

    public handle(request: string): string {
        if (this.nextHandler) {
            return this.nextHandler.handle(request);
        }

        return null;
    }
}

/**
 * تعالج جميع المعالجات المحددة الطلب أو تمرره إلى المعالج التالي
 * في السلسلة.
 */
class MonkeyHandler extends AbstractHandler {
    public handle(request: string): string {
        if (request === 'Banana') {
            return `Monkey: I'll eat the ${request}.`;
        }
        return super.handle(request);

    }
}

class SquirrelHandler extends AbstractHandler {
    public handle(request: string): string {
        if (request === 'Nut') {
            return `Squirrel: I'll eat the ${request}.`;
        }
        return super.handle(request);
    }
}

class DogHandler extends AbstractHandler {
    public handle(request: string): string {
        if (request === 'MeatBall') {
            return `Dog: I'll eat the ${request}.`;
        }
        return super.handle(request);
    }
}

/**
 * عادةً ما يكون كود العميل مُهيأً للعمل مع معالج واحد. في معظم
 * الحالات، لا يدرك حتى أن المعالج جزء من سلسلة.
 */
function clientCode(handler: Handler) {
    const foods = ['Nut', 'Banana', 'Cup of coffee'];

    for (const food of foods) {
        console.log(`Client: Who wants a ${food}?`);

        const result = handler.handle(food);
        if (result) {
            console.log(`  ${result}`);
        } else {
            console.log(`  ${food} was left untouched.`);
        }
    }
}

/**
 * الجزء الآخر من كود العميل يبني السلسلة الفعلية.
 */
const monkey = new MonkeyHandler();
const squirrel = new SquirrelHandler();
const dog = new DogHandler();

monkey.setNext(squirrel).setNext(dog);

/**
 * يجب أن يتمكن العميل من إرسال طلب إلى أي معالج، وليس فقط
 * الأول في السلسلة.
 */
console.log('Chain: Monkey > Squirrel > Dog\n');
clientCode(monkey);
console.log('');

console.log('Subchain: Squirrel > Dog\n');
clientCode(squirrel);

Chain: Monkey > Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
  Monkey: I'll eat the Banana.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.

Subchain: Squirrel > Dog

Client: Who wants a Nut?
  Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
  Banana was left untouched.
Client: Who wants a Cup of coffee?
  Cup of coffee was left untouched.
```

