در طراحی شی گرا **الگوی زنجیره مسئولیت** یک الگوی طراحی متشکل از یک منبع از اشیای فرمانده و یک سری از **اشیای پردازشی** است هر شی پردازشی شامل منطقی است که انواع اشیایی فرمان را می‌تواند پردازش کند؛ بقیه به شی پردازشی بعدی در زنجیره فرستاده می‌شوند. یک مکانیزم نیز برای اضافه کردن شی پردازشی جدید به پایان این زنجیره نیز وجود دارد؛ بنابراین زنجیره مسئولیت نسخه شی‌گرایانه if … else if … else if ....... else … endif است. به علاوه این مزیت را دارد که می‌توان آن را در هنگام اجرا تغییرشکل داد.

این الگو ایده همراهی آزادانه را ترویج می‌دهد.

زنجیره مسئولیت الگوی ساختاری تقریباً یکسان با الگوی آذینگر است با این تفاوت که برای آذینگر همه کلاس‌ها می‌توانند یک درخواست را رسیدگی کنند در حالی که در الگوی زنجیره مسئولیت فقط یکی از کلاس‌ها در زنجیره به درخواست رسیدگی می‌کند.

پشتیبانی از اصول SOLID
----------------------

الگوی زنجیره مسئولیت اصول SOLID را به خوبی پشتیبانی می‌کند. این اصول شامل Single Responsibility Principle، Open/Closed Principle و Liskov Substitution Principle می‌شوند.

اصل SRP می‌گوید که هر کلاس باید فقط یک مسئولیت را داشته باشد. در الگوی زنجیره مسئولیت، هر گام از زنجیره مسئولیت مسئولیت خاص خود را دارد و فقط آن را انجام می‌دهد. به این ترتیب، هر کلاس در این طرح فقط مسئولیت خود را بر عهده دارد و تغییر در یک گام از زنجیره تنها به آن گام اثر می‌گذارد.
اصل OCP می‌گوید که کلاس‌ها باید برای توسعه باز باشند و باید بتوانند با افزودن کدهای جدید، بدون تغییر در کدهای موجود، تغییر کنند. الگوی زنجیره مسئولیت از این اصل پشتیبانی می‌کند زیرا با افزودن یک گام جدید به زنجیره، می‌توان عملکرد سیستم را تغییر داد ولی بدون نیاز به تغییر در کدهای موجود در سایر گام‌ها.
اصل LSP می‌گوید که باید بتوانیم یک شیء را با یک شیء دیگر جایگزین کنیم بدون این که عملکرد کل سیستم تغییر کند. الگوی زنجیره مسئولیت از این اصل پشتیبانی می‌کند زیرا هر گام از زنجیره باید قابلیت جایگزینی با گام دیگری را داشته باشد، به شرطی که هر دو گام به یک نوع از درخواست‌ها پاسخ دهند.

ساختار
------

### دیاگرام UML

یک نمونه UML کلاس و توالی نمودار از الگوی طراحی زنجیره مسئولیت.

مثال در دنیای واقعی
-------------------

وقتی برای پشتیبانی از یک محصول با call center یا مرکز تماس کارخانه تماس می‌گیریم، در واقع داریم این الگو را مشاهده می‌کنیم. ابتدا درخواست ما توسط ماشین مورد ارزیابی قرار می‌گیرد. سپس اگر مشکل حل نشده بود، به یک پاسخ‌گوی غیر متخصص متصل می‌شویم. اگر باز هم مشکل برطرف نشد به یک تکنسین و متخصص متصل می‌شویم تا به احتمال بیشتری مشکل حل شود.

مثال
----

### جاوا

در زیر نمونه‌ای از این الگو در جاوا آورده‌شده‌است. یک لاگر (logger) با استفاده از زنجیره‌ای از لاگرها ایجادمی‌شود، که هرکدام با سطوح مختلف log پیکربندی شده‌اند.

```
import java.util.Arrays;
import java.util.EnumSet;
import java.util.function.Consumer;

@FunctionalInterface
public interface Logger {
 public enum LogLevel {
 INFO, DEBUG, WARNING, ERROR, FUNCTIONAL\_MESSAGE, FUNCTIONAL\_ERROR;

 public static LogLevel[] all() {
 return values();
 }
 }

 abstract void message(String msg, LogLevel severity);

 default Logger appendNext(Logger nextLogger) {
 return (msg, severity) -> {
 message(msg, severity);
 nextLogger.message(msg, severity);
 };
 }

 static Logger writeLogger(LogLevel[] levels, Consumer<String> stringConsumer) {
 EnumSet<LogLevel> set = EnumSet.copyOf(Arrays.asList(levels));
 return (msg, severity) -> {
 if (set.contains(severity)) {
 stringConsumer.accept(msg);
 }
 };
 }

 static Logger consoleLogger(LogLevel... levels) {
 return writeLogger(levels, msg -> System.err.println("Writing to console: "+ msg));
 }

 static Logger emailLogger(LogLevel... levels) {
 return writeLogger(levels, msg -> System.err.println("Sending via email: "+ msg));
 }

 static Logger fileLogger(LogLevel... levels) {
 return writeLogger(levels, msg -> System.err.println("Writing to Log File: "+ msg));
 }

 public static void main(String[] args) {
 // Build an immutable chain of responsibility
 Logger logger = consoleLogger(LogLevel.all())
 .appendNext(emailLogger(LogLevel.FUNCTIONAL\_MESSAGE, LogLevel.FUNCTIONAL\_ERROR))
 .appendNext(fileLogger(LogLevel.WARNING, LogLevel.ERROR));

 // Handled by consoleLogger since the console has a LogLevel of all
 logger.message("Entering function ProcessOrder().", LogLevel.DEBUG);
 logger.message("Order record retrieved.", LogLevel.INFO);

 // Handled by consoleLogger and emailLogger since emailLogger implements Functional\_Error & Functional\_Error
 logger.message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FUNCTIONAL\_ERROR);
 logger.message("Order Dispatched.", LogLevel.FUNCTIONAL\_MESSAGE);

 // Handled by consoleLogger and fileLogger since fileLogger implements Warning & Error
 logger.message("Customer Address details missing in Branch DataBase.", LogLevel.WARNING);
 logger.message("Customer Address details missing in Organization DataBase.", LogLevel.ERROR);
 }
}

```

### پایتون

```
"""
Chain of responsibility pattern example.
"""
from abc import ABCMeta, abstractmethod
from enum import Enum, auto

class LogLevel(Enum):
 """
 Log Levels Enum.
 """
    NONE = auto()
    INFO = auto()
    DEBUG = auto()
    WARNING = auto()
    ERROR = auto()
    FUNCTIONAL\_MESSAGE = auto()
    FUNCTIONAL\_ERROR = auto()
    ALL = auto()

class Logger:
 """
 Abstract handler in chain of responsibility pattern.
 """
    \_\_metaclass\_\_ = ABCMeta

    next = None

    def \_\_init\_\_(self, levels):
 """
 Initialize new logger

 Args:
 levels (list[str]): List of log levels.
 """
        self.log\_levels = []

        for level in levels:
            self.log\_levels.append(level)

    def set\_next(self, next\_logger):
 """
 Set next responsible logger in the chain.

 Args:
 next\_logger (Logger): Next responsible logger.

 Returns:
 Logger: Next responsible logger.
 """
        self.next = next\_logger
        return self.next

    def message(self, msg, severity):
 """
 Message writer handler.

 Args:
 msg (str): Message string.
 severity (LogLevel): Severity of message as log level enum.
 """
        if LogLevel.ALL in self.log\_levels or severity in self.log\_levels:
            self.write\_message(msg)

        if self.next is not None:
            self.next.message(msg, severity)

    @abstractmethod
    def write\_message(self, msg):
 """
 Abstract method to write a message.

 Args:
 msg (str): Message string.

 Raises:
 NotImplementedError
 """
        raise NotImplementedError("You should implement this method.")

class ConsoleLogger(Logger):
    def write\_message(self, msg):
 """
 Overrides parent's abstract method to write to console.

 Args:
 msg (str): Message string.
 """
        print("Writing to console:", msg)

class EmailLogger(Logger):
 """
 Overrides parent's abstract method to send an email.

 Args:
 msg (str): Message string.
 """
    def write\_message(self, msg):
        print("Sending via email:", msg)

class FileLogger(Logger):
 """
 Overrides parent's abstract method to write a file.

 Args:
 msg (str): Message string.
 """
    def write\_message(self, msg):
        print("Writing to log file:", msg)

def main():
 """
 Building the chain of responsibility.
 """
    logger = ConsoleLogger([LogLevel.ALL])
    email\_logger = logger.set\_next(
        EmailLogger([LogLevel.FUNCTIONAL\_MESSAGE, LogLevel.FUNCTIONAL\_ERROR])
    )
    # As we don't need to use file logger instance anywhere later
    # We will not set any value for it.
    email\_logger.set\_next(
        FileLogger([LogLevel.WARNING, LogLevel.ERROR])
    )

    # ConsoleLogger will handle this part of code since the message
    # has a log level of all
    logger.message("Entering function ProcessOrder().", LogLevel.DEBUG)
    logger.message("Order record retrieved.", LogLevel.INFO)

    # ConsoleLogger and FileLogger will handle this part since file logger
    # implements WARNING and ERROR
    logger.message(
        "Customer Address details missing in Branch DataBase.",
        LogLevel.WARNING
    )
    logger.message(
        "Customer Address details missing in Organization DataBase.",
        LogLevel.ERROR
    )

    # ConsoleLogger and EmailLogger will handle this part as they implement
    # functional error
    logger.message(
        "Unable to Process Order ORD1 Dated D1 for customer C1.",
        LogLevel.FUNCTIONAL\_ERROR
    )
    logger.message("OrderDispatched.", LogLevel.FUNCTIONAL\_MESSAGE)

if \_\_name\_\_ == "\_\_main\_\_":
    main()

```

جستارهای وابسته
---------------

* نرم‌افزار طراحی الگوی
* اصل یک مسئولیت

منابع
-----

1. ↑  «نسخه آرشیو شده». بایگانی‌شده از اصلی در ۲۷ فوریه ۲۰۱۸. دریافت‌شده در ۱۶ فوریه ۲۰۱۸.
2. ↑  "The Chain of Responsibility design pattern - Structure and Collaboration". *w3sDesign.com*. Retrieved 2017-08-12.

| * ن
* ب
* و
الگوهای طراحی |
| --- |
| الگوهای طراحی GO4 | 

|  |  |
| --- | --- |
| ایجاد | 
* الگوی کارخانه انتزاعی
* الگوی سازنده
* الگوی متد کارخانه شیء
* الگوی نمونه اولیه
* الگوی یگانه

 |
| ساختاری | 
* آداپتور
* پل
* کامپوزیت
* آذینگر
* نما
* مگس وزن
* وکالت

 |
| رفتاری | 
* زنجیره مسئولیت
* الگوی فرمان
* مفسر
* الگوی تکرار
* میانجی
* یادگاری
* ناظر
* وضعیت
* استراتژی
* متد الگو
* بازدیدگر

 |

 |
| Concurrencypatterns | 
* Active object
* Balking
* Binding properties
* Double-checked locking
* Event-based asynchronous
* Guarded suspension
* Join
* قفل
* مانیتور
* Proactor
* Reactor
* Read write lock
* زمان‌بندی
* الگوی مخزن نخ
* Thread-local storage

 |
| الگوهایمعماری | 
* Front controller
* مفسر
* مدل-نما-کنترل‌گر
* ADR
* Entity-component-system
* چندلایه
* Specification
* Publish–subscribe
* اشیای لخت
* Service locator
* ثبت کنشور
* Identity map
* شی دسترسی به داده
* شی انتقال داده
* وارونگی کنترل
* Model 2

 |
| دیگرالگوها | 
* Blackboard
* Business delegate
* Composite entity
* تزریق نیازمندی
* Intercepting filter
* بارگیری تنبلانه
* شیء ساختگی
* Null object
* استخر اشیاء
* Servant
* Twin
* Type tunnel
* Method chaining

 |
| کتاب‌ها | 
* *الگوهای طراحی*
* *Enterprise Integration Patterns*
* *Patterns of Enterprise Application Architecture*
* *Analysis patterns*

 |
| افراد | 
* کریستوفر الکساندر
* Erich Gamma
* Ralph Johnson
* John Vlissides
* گریدی بوچ
* کنت بک
* وارد کانینگهام
* مارتین فولر
* رابرت سسیل مارتین
* Jim Coplien
* Douglas Schmidt
* Linda Rising

 |
| جوامع | 
* The Hillside Group
* The Portland Pattern Repository

 |