7a12

الگوی طراحی زنجیره مسئولیت در سی شارپ

لینک کوتاه https://codecell.ir/a/7a12
به اشتراک گذاری
نویسنده:
0
0
2
آموزش های نویسنده:
الگوی طراحی Chain of Responsibility در سی شارپ

استفاده از الگوهای طراحی اثبات شده می تواند به طور قابل توجهی کارایی و قابلیت نگهداری کد ما را افزایش دهد. یکی از این الگوها زنجیره مسئولیت(Chain of Responsibility) است که راه حلی زیبا برای مدیریت سناریوهای گردش کار پیچیده ارائه می دهد. در این مقاله، پیچیدگی‌های الگوی طراحی زنجیره مسئولیت را بررسی می‌کنیم و مفاهیم اصلی، مزایا و کاربردهای عملی آن را با ذکر یک مثال‌ مورد بحث قرار می‌دهیم.

 الگوی طراحی زنجیره مسئولیت یا Chain of Responsibility Design Pattern چیست؟

الگوی زنجیره مسئولیت یک الگوی طراحی رفتاری(behavioral design pattern) است که اجازه می‌دهد یک درخواست در امتداد زنجیره‌ای از کنترل‌کننده‌های بالقوه ارسال شود تا زمانی که درخواست مناسب برای پردازش آن را پیدا کند. هر کنترل کننده در زنجیره دارای استقلال برای رسیدگی به درخواست یا delegate آن به کنترل کننده بعدی است. یعنی پس از دریافت درخواست، هر کنترل کننده تصمیم می گیرد یا درخواست را پردازش کند یا آن را به کنترل کننده بعدی در زنجیره ارسال کند.

 این رویکرد انعطاف پذیری، مقیاس پذیری و قابلیت نگهداری را در سناریوهای مدیریت گردش کار(workFlow) ارتقا می دهد.

مانند بسیاری دیگر از الگوهای طراحی رفتاری، زنجیره مسئولیت متکی بر تبدیل رفتارهای خاص به اشیاء مستقل به نام کنترل کننده(handler) است.

این الگو زمانی توصیه می‌شود که چندین شی می‌توانند یک درخواست را مدیریت کنند و نیازی نیست که کنترل‌کننده یک شی خاص باشد. همچنین، کنترل کننده در زمان اجرا تعیین می شود.

مثال استفاده از Chain of Responsibility Design Pattern در سی شارپ:

بیایید سناریویی را در نظر بگیریم که در آن یک سری قوانین تخفیف برای یک برنامه تجارت الکترونیکی داریم. بسته به مشخصات مشتری، می خواهیم درصدهای تخفیف متفاوتی را برای سفارشات آنها اعمال کنیم.

قوانین تخفیف به شرح زیر است:

  • اگر مشتری VIP است، 20 درصد تخفیف اعمال کنید.
  • اگر مشتری مشتری دائمی است، 10 درصد تخفیف اعمال کنید.
  • اگر مشتری مشتری جدید است، 5 درصد تخفیف اعمال کنید.
  • اگر هیچ یک از قوانین بالا مطابقت نداشت، از تخفیف استفاده نکنید.

در ابتدا، ما می توانیم این منطق را با استفاده از یک سری دستورات If مدیریت کنیم:

public class Customer
{
    public bool IsVIP { get; set; }
    public bool IsRegular { get; set; }
    public bool IsNew { get; set; }
}
Public decimal CalculateDiscount(Customer customer, decimal orderTotal)
{
    return customer switch
    {
        { IsVIP: true } => orderTotal * 0.8m,
        { IsRegular: true } => orderTotal * 0.9m,
        { IsNew: true } => orderTotal * 0.95m,
        _ => 0
    };
}
var customer=new Customer { IsNew = true };


Console.WriteLine(CalculateDiscount(customer, 10_000));

در حالی که رویکرد دستورات If کار می کند، زمانی که تعداد قوانین افزایش می یابد، می تواند دشوار شود.

الگوی زنجیره مسئولیت راه حلی انعطاف پذیرتر و قابل نگهداری را ارائه می دهد.

بیایید برای استفاده از این الگو، کد را refactor کنیم.

مرحله 1: یک کلاس کنترل کننده انتزاعی(abstract) به نام DiscountHandler ایجاد کنید که یک رابط مشترک برای همه کنترل کننده های تخفیف تعریف می کند:

public abstract class DiscountHandler
 {
     protected DiscountHandler _nextHandler;

     public DiscountHandler SetNextHandler(DiscountHandler nextHandler)
     {
         _nextHandler = nextHandler;
         return _nextHandler;
     }
     public abstract decimal CalculateDiscount(Customer customer, decimal orderTotal);
 }

مرحله شماره 2: کنترل کننده یا handler های تخفیف را با استفاده از DiscountHandler پیاده سازی کنید. هر کنترل کننده قانون خاصی را مدیریت می کند و تصمیم می گیرد که آیا تخفیف اعمال کند یا درخواست را به کنترل کننده بعدی ارسال کند.

 //VIPDiscountHandler
public class VIPDiscountHandler : DiscountHandler
{
    public override decimal CalculateDiscount(Customer customer, decimal orderTotal)
    {
        if (customer.IsVIP)
        {
            return orderTotal * 0.8m;
        }
        return _nextHandler.CalculateDiscount(customer, orderTotal);
    }
}
//RegularDiscountHandler
public class RegularDiscountHandler : DiscountHandler
 {
     public override decimal CalculateDiscount(Customer customer, decimal orderTotal)
     {
         if (customer.IsRegular)
         {
             return orderTotal * 0.9m;
         }

         return _nextHandler.CalculateDiscount(customer, orderTotal);
     }
 }
//NewCustomerDiscountHandler
public class NewDiscountHandler : DiscountHandler
 {
     public override decimal CalculateDiscount(Customer customer, decimal orderTotal)
     {
         if (customer.IsNew)
         {
             return orderTotal * 0.95m;
         }

         return _nextHandler.CalculateDiscount(customer, orderTotal);
     }
 }
//NoDiscountHandler
public class NoDiscountHandler : DiscountHandler
 {
     public override decimal CalculateDiscount(Customer customer, decimal orderTotal)
     {
         return 0; //no discount
     }
 }

مرحله 3: با استفاده از این هندلرها، می توانیم زنجیره مسئولیت را با اتصال آن ها به یکدیگر ایجاد کنیم:

var vipHandler = new VIPDiscountHandler();
vipHandler.SetNextHandler(new RegularDiscountHandler())
          .SetNextHandler(new NewDiscountHandler())
          .SetNextHandler(new NoDiscountHandler());

در نهایت، می‌توانیم زنجیره را با فراخوانی متد CalculateDiscount در اولین کنترلر در زنجیره فراخوانی کنیم:

decimal discountAmount = vipHandler.CalculateDiscount(customer, 10_000);
Console.WriteLine(discountAmount);

برای مشاهده این ویدیو در یوتیوب اینجا کلیک کنید.

برای دریافت سورس پروژه اینجا کلیک کنید.

مزایای استفاده از الگوی زنجیره مسئولیت

الگوی زنجیره مسئولیت چندین مزیت را هنگام رسیدگی به گردش‌های کاری پیچیده ارائه می‌کند:

  • انعطاف‌پذیری و مقیاس‌پذیری: این الگو امکان پیکربندی مجدد زنجیره گردش کار را به صورت دینامیک فراهم می‌آورد و امکان افزودن، حذف یا اصلاح آسان کنترل‌کننده‌ها را بدون تأثیر بر منطق اصلی فراهم می‌کند. این انعطاف‌پذیری، مدیریت یکپارچه گردش کار و گسترش آن در آینده را تسهیل می‌کند.
  • کد قابل نگهداری و ماژولار: هر کنترل کننده بر روی یک کار خاص تمرکز می کند و تضمین می کند که کد مختصر، ماژولار و دارای نگهداری آسان است. تفکیک مسئولیت ها اشکال زدایی، تست و بروز رسانی را ساده می کند.
  • توسعه پذیری پیشرفته: الگوی زنجیره مسئولیت استفاده مجدد از کد را ترویج می کند، زیرا کنترل کننده ها را می توان به راحتی تغییر داد یا جایگزین کرد تا نیازهای در حال تحول را برآورده کنند. کنترل‌کننده‌های جدیدی را می‌توان برای رسیدگی به مراحل یا الزامات اضافی بدون تغییر کد موجود اضافه کرد.

موارد استفاده از الگوی زنجیره مسئولیت

الگوی زنجیره مسئولیت در حوزه های مختلف کاربردهای عملی پیدا می کند.

  • گردش کار و فرآیندهای تأیید: هر سناریویی که شامل گردش کار چند مرحله ای یا فرآیندهای تأیید باشد می تواند از الگوی زنجیره مسئولیت بهره مند شود. این الگو انتقال یکپارچه بین مراحل را امکان پذیر می کند و مدیریت استثناها(exception) یا ردها(rejection) را در هر مرحله تسهیل می کند.
  • مدیریت رویداد: سیستم‌هایی که رویدادها(event) را پردازش می‌کنند، مانند فریمورک های UI یا معماری‌های رویداد محور(event-driven architecture)، می‌توانند از الگوی Chain of Responsibility برای انتشار رویدادها از طریق یک سری از کنترل‌کننده‌ها استفاده کنند که هر کدام مسئول نوع یا جنبه خاصی از رویداد هستند.
  • مدیریت و ثبت خطا: این الگو را می‌توان برای مدیریت خطاها(error handling) یا سناریوهای گزارش‌گیری(logging) که در آن کنترل‌کننده‌های مختلف خطاها یا لاگ ها را بر اساس شدت(severity) یا نوع آن‌ها پردازش می‌کنند، استفاده کرد.

نتیجه‌گیری

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

دیگر مقالات آموزش برنامه نویسی مدرس

Response Caching در ASP.NET Core

Response Caching یک مکانیزم ذخیره سازی پاسخ سرور توسط مرورگر یا سایر کلاینت ها است. با استفاده از Response Caching در Asp.net Core می توانیم عملکرد و کارایی سیستم را بالا ببریم.

669 0 1402/10/22

Output Caching در ASP.NET Core 8.0

Output Caching یک ویژگی جدید است که از زمان .NET 7 معرفی شده است. این ویژگی به ما این امکان را می دهد که به راحتی یک کش پاسخ برای Web API خود بدون پیاده سازی IMemoryCache راه اندازی کنیم.

723 0 1402/10/14

ViewComponent در ASP.NET Core

در ASP.NET Core با استفاده از ViewComponent ها می توان اجزای ماژولار، قابل استفاده مجدد، قابل نگهداری و مقیاس پذیر برای ساخت برنامه های کاربردی وب ایجاد کرد. در این مقاله به نحوه ایجاد و فراخوانی ViewComponent در Asp.net core پرداخته ایم.

1٬431 2 1402/05/15

تزریق وابستگی در ASP.NET Core

تزریق وابستگی (DI) یک الگوی طراحی نرم افزاری است که امکان ایجاد برنامه های کاربردی و ماژولار را فراهم می کند.. در .NET Core تزریق وابستگی یا Dependency injection یک ویژگی مهم است که می تواند برای ساده سازی توسعه برنامه، بهبود تست پذیری و کاهش پیچیدگی کد مورد استفاده قرار گیرد.

1٬964 1 1402/02/04

ضروری ترین کتابخانه های NuGet برای ASP.NET Core

در این مقاله مهمترین،ضروری ترین و پرکاربردترین کتابخانه های NuGet که هر توسعه‌ دهنده‌ ASP.NET Core باید برای توسعه بهتر و کاهش زمان مورد نیاز برای برنامه ‌های خود از آن استفاده کنند را مورد بررسی قرار داده ایم.

1٬517 1 1401/12/29

مقایسه List و Array در سی شارپ

آرایه و لیست در سی شارپ هر دو به عنوان مجموعه ای از مقادیر عمل می کنند، اما در نحوه ذخیره محتوای خود در حافظه و نحوه دسترسی به آنها متفاوت هستند. در این مقاله Benchmark و کارایی List<T> با سایز داینامیک، List<T> با سایز ثابت و Array ها را بررسی می کنیم.

2٬221 2 1401/09/01

LinkedList در سی شارپ

LinkedList یا لیست پیوندی در سی شارپ یک ساختار داده خطی است که عنصر را در مکان غیر پیوسته ذخیره می کند. LinkedList شامل گره هایی است که هر گره حاوی یک فیلد داده و یک مرجع (پیوند) به گره بعدی در لیست است. در سی شارپ، LinkedList یا لیست پیوندی یک نوع مجموعه جنریک است.

2٬046 0 1401/08/13

Garbage Collection در دات نت

به طور کلی، Garbage Collection (GC) یا جمع آوری زباله در .Net چیزی نیست جز به دست آوردن مجدد حافظه اختصاص داده شده به اشیایی که در حال حاضر در هیچ بخشی از برنامه ما استفاده نمی شوند. ما در این مقاله Garbage Collection را در سی شارپ بررسی خواهیم کرد.

2٬838 5 1401/03/30

.NET Core چیست؟

.Net (با تلفظ «دات نت») یک چارچوب نرم افزاری کامپیوتری مدیریت شده رایگان و منبع باز برای سیستم عامل های ویندوز، لینوکس و macOS است. این پروژه در درجه اول توسط کارمندان مایکروسافت از طریق دات نت توسعه یافته و تحت مجوز MIT منتشر شده است.

2٬587 2 1401/03/16

پشته(Stack) در سی شارپ

پشته یا Stack در سی شارپ یک نوع خطی از ساختار داده است که قادر به ذخیره اشیاء است. پشته یک ساختار داده LIFO یا Last-In-First-Out است، به این معنی که آخرین موردی که در پشته قرار می گیرد اولین موردی است که از پشته خارج می شود.

2٬187 0 1401/03/09

صف (Queue) در سی شارپ

صف (Queue) در سی شارپ یک نوع خطی از ساختار داده است که قادر به ذخیره اشیاء است. Queue یک ساختار داده first-in-first-out یا FIFO است که به این معنی است که اولین مورد اضافه شده به صف اولین موردی است که حذف می شود.

2٬162 0 1401/02/30

تفاوت Hashtable و Dictionary در سی شارپ

در سی شارپ از Hashtable و Dictionary می توان برای ذخیره مجموعه‌ای از داده‌ها، شبیه به List معمولی استفاده کرد. با این تفاوت که Hashtable و Dictionary عناصر را به عنوان جفت Key/Value ذخیره می کنند.در این مقاله به تفاوت های Hashtable و Dictionary پرداخته شده است.

1٬843 1 1401/02/23

Dictionary در سی شارپ

در سی شارپ از دیکشنری ها (Dictionary) می‌توان برای ذخیره مجموعه‌ای از داده‌ها، شبیه به List معمولی استفاده کرد. تفاوت اصلی این است که یک Dictionary می تواند عناصر را به عنوان جفت Key/Value ذخیره کند.Key ها باید منحصر به فرد و نمی توانند null باشند. Value ها می توانند تکراری یا null باشند.

2٬249 3 1401/02/17

Hashtable در سی شارپ

از Hashtable می‌توان برای ذخیره مجموعه‌ای از داده‌ها، شبیه به List معمولی استفاده کرد. تفاوت اصلی این است که یک Hashtable می تواند عناصر را به عنوان جفت Key/Value به عنوان جایگزینی برای استفاده از Index ذخیره کند.

1٬721 5 1401/02/14

Redirect درخواست (ریدایرکت) در asp.net core

در برنامه های ASP.NET Core برای تغییر مسیر(ریدایرکت) و Redirect به یک URL خاص روش های مختلفی وجود دارد. در این مقاله با این تکنیک ها و کدهای مورد نیاز برای تغییر مسیر یک درخواست در ASP.NET Core آشنا می شویم.

2٬562 5 1401/02/12

تبدیل enum به لیست انتخابی در asp.net core

در این آموزش ما بوسیله Reflection ها در سی شارپ و asp.net core یک enum را به لیست انتخابی یا SelectListItem تبدیل خواهیم کرد و بوسیله تگ select در بوت استرپ 5 نمایش می دهیم.

1٬753 3 1401/02/03

نحوه ارسال ایمیل در asp و c#

امروزه ارسال ایمیل به امری ضروری در پروژه های وب تبدیل شده است.از ارسال ایمیل در asp می توان در بخش های تایید حساب کاربری،بازیابی رمز عبور،ایمیل مارکتینگ،ارسال خبرنامه و ... استفاده نمود.در این آموزش نحوه ارسال ایمیل در asp core و سی شارپ پیاده سازی گردیده است.

2٬582 5 1401/02/03
نظرات

برای ثبت نظر باید در سایت ثبت نام یا ورود نمایید