أنماط التصميم المتقدمة في C#: من النظرية إلى التطبيق
أنماط التصميم (Design Patterns) هي حلول مثبتة للمشكلات النمطية في هندسة البرمجيات. على المستوى المبتدئ، يتعرف المطورون على Singleton أو Factory أو Adapter. ومع ذلك، لإنشاء أنظمة مرنة وقابلة للصيانة والتوسع على منصة .NET، من الضروري إتقان أنماط سلوكية وهيكلية أكثر تعقيداً. في هذه المقالة، سنشرح ثلاثة أنماط متقدمة: Chain of Responsibility وState وVisitor. سيتم توضيح كل نمط بمثال عملي بلغة C# باستخدام الإمكانيات الحديثة للغة (records, pattern matching, generics).
1. Chain of Responsibility (سلسلة المسؤوليات)
يسمح نمط Chain of Responsibility بتمرير الطلب بشكل تسلسلي عبر سلسلة من المعالجات، حتى يقوم أحدهم بمعالجة الطلب. هذا يلغي الارتباط الصارم بين المرسل والمستقبل. في C#، يُستخدم غالباً في middleware في ASP.NET Core أو للتحقق من صحة البيانات.
مثال: نظام التحقق من صلاحيات الوصول
لنفترض أن لدينا طلباً لتنفيذ عملية. يتحقق كل معالج من شرط واحد (المصادقة، التفويض، الحدود).
// الفئة الأساسية للمعالجpublic abstract class Handler{ protected Handler? NextHandler;
public void SetNext(Handler handler) => NextHandler = handler;
public abstract void Handle(RequestContext context);}
public class AuthenticationHandler : Handler{ public override void Handle(RequestContext context) { if (context.IsAuthenticated) { Console.WriteLine("تمت المصادقة بنجاح."); NextHandler?.Handle(context); } else { Console.WriteLine("خطأ: المستخدم غير مصادق عليه."); } }}
public class AuthorizationHandler : Handler{ public override void Handle(RequestContext context) { if (context.Role == "Admin") { Console.WriteLine("تم التفويض بنجاح."); NextHandler?.Handle(context); } else { Console.WriteLine("خطأ: صلاحيات غير كافية."); } }}
// سياق الطلبpublic record RequestContext(bool IsAuthenticated, string Role);
// الاستخدامvar authHandler = new AuthenticationHandler();var authzHandler = new AuthorizationHandler();authHandler.SetNext(authzHandler);
var context = new RequestContext(true, "Admin");authHandler.Handle(context);// الإخراج:// تمت المصادقة بنجاح.// تم التفويض بنجاح.هذا النمط مثالي لإنشاء خطوط أنابيب المعالجة، حيث يمكن لكل خطوة إيقاف التنفيذ أو تمرير التحكم إلى الخطوة التالية.
2. State (الحالة)
يسمح نمط State للكائن بتغيير سلوكه عند تغير حالته الداخلية. من الخارج، يبدو الأمر كما لو أن الكائن يغير فئته. في C#، من السهل تنفيذه باستخدام الواجهات والتكوين (composition).
مثال: إدارة طلب في متجر إلكتروني
يمكن أن يكون الطلب في حالات: جديد، مدفوع، تم الشحن، تم التوصيل. تحدد كل حالة الإجراءات المسموح بها.
// واجهة الحالةpublic interface IOrderState{ void Pay(Order order); void Ship(Order order); void Deliver(Order order);}
// الحالات المحددةpublic class NewOrderState : IOrderState{ public void Pay(Order order) { Console.WriteLine("تم دفع الطلب."); order.State = new PaidOrderState(); }
public void Ship(Order order) => Console.WriteLine("خطأ: الطلب لم يتم دفعه بعد."); public void Deliver(Order order) => Console.WriteLine("خطأ: الطلب لم يتم شحنه بعد.");}
public class PaidOrderState : IOrde
```