دیزاین پترن Chain of Responsibility
یکی از زیرشاخه های الگوهای طراحی، Behavioral Design Patterns است. تمرکز و وظیفه اصلی این دیزاین پترن ها تعامل اشیاء و جداسازی وظایف آن ها از یکدیگر است.
Chain of Responsibility Design Pattern
دیزاین پترن Chain of Responsibility یکی از زیرشاخه های الگوهای طراحی از نوع Behavioral است.
الگوی طراحی زنجیره مسئولیتها (Chain of Responsibility) از متصل کردن فرستنده درخواست به گیرنده آن با دادن فرصت به بیش از یک شی برای رسیدگی به درخواست جلوگیری می کند. این الگو اشیاء گیرنده را زنجیر می کند و درخواست را در امتداد زنجیره ارسال می کند تا زمانی که شیئی آن را کنترل کند.
سختش نکنیم! ما با استفاده از این دیزاین پترن میتوانیم زنجیره ای از کارها را پشت سر هم انجام دهیم بدون اینکه از بیرون بخواهیم این کارها را جداگانه انجام بدیم. در مثالی که در ادامه میزنیم، وظیفه لاگ کردن در فایل، در کنسول و یا نمایش Error را از هم جدا کرده ایم اما سطح خطا از سطح فایل و سطح فایل از سطح کنسول بالاتر است و میخواهیم بر اساس سطح ورودی لاگ های جداگانه را پشت سر هم بزنیم.
میزان استفاده :
متوسط رو به پایین
پیاده سازی دیزاین پترن Chain of Responsibility
ما میخواهیم لاگ های نرم افزار را به ۳ سطح دسته بندی کنیم. سطوح Info, Debug و Error. بنابراین یک enum به شکل زیر داریم.
public enum LogLevel { INFO = 1, DEBUG = 2, ERROR = 3 }
همچنین علاوه بر سطوح لاگ، کلاس هایی جهت مدیریت لاگ های Console, File و Error ها داریم.
کلاس ConsoleLogger را به شکل زیر نوشتیم.
public class ConsoleLogger : AbstractLogger { public ConsoleLogger(LogLevel level) { this.level = level; } protected override void Write(string message) { Console.WriteLine("Standard Console::Logger: " + message); } }
کلاس ErrorLogger را به شکل زیر نوشتیم.
public class ErrorLogger : AbstractLogger { public ErrorLogger(LogLevel level) { this.level = level; } protected override void Write(String message) { Console.WriteLine("Error Console::Logger: " + message); } }
کلاس FileLogger را به شکل زیر نوشتیم.
public class FileLogger : AbstractLogger { public FileLogger(LogLevel level) { this.level = level; } protected override void Write(String message) { Console.WriteLine("File::Logger: " + message); } }
همینطور که از کدهای بالا مشخص است، هر کدام یک متد جهت Write را override کرده اند. اما کلاس parent آنها که AbstractLogger است چه چیزی دارد که این دیزاین پترن را متمایز میکند؟
public abstract class AbstractLogger { protected LogLevel level; protected AbstractLogger nextLogger; public void SetNextLogger(AbstractLogger nextLogger) { this.nextLogger = nextLogger; } public void LogMessage(LogLevel level, String message) { if (this.level <= level) { Write(message); } if (nextLogger != null) { nextLogger.LogMessage(level, message); } } abstract protected void Write(String message); }
خب خب خب! ما توی این کلاس یک فیلد enumای از نوع LogLevel داریم که مشخص کننده سطح لاگ این کلاس است.
یک فیلد دیگر از نوع همین کلاس یعنی AbstractLogger داریم که از طریق متد SetNextLogger مقدار دهی می شود. اما چرا SetNextLogger؟
قلب تپنده این دیزاین پترن دقیقا همین متد است!
ما از طریق همین متد لاگ کننده بعدی این کلاس را مشخص میکنیم.
مطالب بعدی LogMessage است که وظیفه نمایش و ذخیره لاگ راه در لاگ کنندههای سطح های پایین تر را بر عهده دارد. در ابتدا سطح فعلی با سطح وارد شده از متود را بررسی می کند و در صورتی که لاگ کننده بعدی برای این کلاس وجود داشت متد LogMessage که همین متد است را از لاگ کننده بعدی صدا میزند.
و در نهایت متد Write را داریم که از نوع abstract است.
static void Main(string[] args) { try { ShowMessage("Chains Of Responsibility Design Pattern"); AbstractLogger loggerChain = getChainOfLoggers(); loggerChain.LogMessage(LogLevel.INFO, "This is an information."); loggerChain.LogMessage(LogLevel.DEBUG, "This is an debug level information."); loggerChain.LogMessage(LogLevel.ERROR, "This is an error information."); } catch (Exception ex) { ShowError(ex.Message); } Console.ReadLine(); } private static AbstractLogger getChainOfLoggers() { AbstractLogger errorLogger = new ErrorLogger(LogLevel.ERROR); AbstractLogger fileLogger = new FileLogger(LogLevel.DEBUG); AbstractLogger consoleLogger = new ConsoleLogger(LogLevel.INFO); errorLogger.SetNextLogger(fileLogger); fileLogger.SetNextLogger(consoleLogger); return errorLogger; }
خروجی کد بالا را میتوانیم در ادامه ببینیم.
Chains Of Responsibility Design Pattern ================================================= Standard Console::Logger: This is an information. ================================================= File::Logger: This is an debug level information. Standard Console::Logger: This is an debug level information. ================================================= Error Console::Logger: This is an error information. File::Logger: This is an error information. Standard Console::Logger: This is an error information.
نظرات