الگوی زنجیره مسئولیت
در طراحی شی گرا الگوی زنجیره مسئولیت یک الگوی طراحی متشکل از یک منبع از اشیای فرمانده و یک سری از اشیای پردازشی است[1] هر شی پردازشی شامل منطقی است که انواع اشیایی فرمان را میتواند پردازش کند؛ بقیه به شی پردازشی بعدی در زنجیره فرستاده میشوند. یک مکانیزم نیز برای اضافه کردن شی پردازشی جدید به پایان این زنجیره نیز وجود دارد؛ بنابراین زنجیره مسئولیت نسخه شیگرایانه if … else if … else if ....... else … endif است. به علاوه این مزیت را دارد که میتوان آن را در هنگام اجرا تغییرشکل داد.
این الگو ایده همراهی آزادانه را ترویج میدهد.
زنجیره مسئولیت الگوی ساختاری تقریباً یکسان با الگوی آذینگر است با این تفاوت که برای آذینگر همه کلاسها میتوانند یک درخواست را رسیدگی کنند در حالی که در الگوی زنجیره مسئولیت فقط یکی از کلاسها در زنجیره به درخواست رسیدگی میکند.
ساختار
دیاگرام UML
مثال
جاوا
در زیر نمونهای از این الگو در جاوا آوردهشدهاست. یک لاگر (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()
جستارهای وابسته
- نرمافزار طراحی الگوی
- اصل یک مسئولیت
منابع
- «نسخه آرشیو شده». بایگانیشده از اصلی در ۲۷ فوریه ۲۰۱۸. دریافتشده در ۱۶ فوریه ۲۰۱۸.
- "The Chain of Responsibility design pattern - Structure and Collaboration". w3sDesign.com. Retrieved 2017-08-12.