التصميم الساكن مقابل تصميم النسخ
قرّروا متى تكون الحالة الساكنة مناسبة
التصميم الساكن مقابل تصميم النسخ درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.
قرار تصميمي
يُعد اختيار static أو instance قرارًا تصميميًا. والسؤال الأساسي هو: هل يعتمد السلوك على حالة خاصة بكل كائن، أم على مدخلاته فقط؟
using System;
class Program
{
// Depends only on inputs -> good static method
static int Max(int a, int b) => a > b ? a : b;
static void Main()
{
Console.WriteLine(Max(3, 8));
}
}استخدم static للمنطق عديم الحالة
إذا لم تحتج الدالة إلى حقول الكائن وكانت تكتفي بتحويل المدخلات، فاجعلها static. وتُعد مساعدات الرياضيات والمنسّقات أمثلة مناسبة لذلك.
using System;
static class Convert2
{
public static double MilesToKm(double miles) => miles * 1.60934;
}
class Program
{
static void Main()
{
Console.WriteLine(Convert2.MilesToKm(10).ToString("0.0") + " km");
}
}استخدم instance للحالة
إذا كان السلوك يعتمد على بيانات تختلف من كائن إلى آخر، فاستخدم instance. إذ يحتفظ كل كائن بحالته الخاصة.
using System;
class Counter
{
private int _count;
public void Increment() => _count++;
public int Value => _count;
}
class Program
{
static void Main()
{
var a = new Counter();
var b = new Counter();
a.Increment();
a.Increment();
b.Increment();
Console.WriteLine("a=" + a.Value + ", b=" + b.Value);
}
}الحالة المشتركة هي حالة عامة
يُعد الحقل static عامًّا فعليًا. وقد يتسبب في أخطاء دقيقة عندما تقرأه أجزاء عديدة من البرنامج وتكتب فيه. فضّل حالة الكائن عندما يحتاج كل مستخدم إلى نسخته الخاصة.
using System;
class BadCart
{
public static int Items; // shared by EVERYONE -> usually wrong for a cart
}
class Program
{
static void Main()
{
BadCart.Items++;
BadCart.Items++;
Console.WriteLine("All carts share: " + BadCart.Items);
}
}قابلية الاختبار
من السهل اختبار الدوال static الخالصة: المدخل نفسه يعطي المخرج نفسه. أما الحالة static القابلة للتغيير فتتسرب بين الاختبارات وتجعلها هشة.
using System;
static class Calc
{
public static int Add(int a, int b) => a + b; // trivially testable
}
class Program
{
static void Main()
{
Console.WriteLine(Calc.Add(2, 2) == 4 ? "pass" : "fail");
}
}استخدم static للمساعدات المنشئة
تُعد دوال factory static طريقة واضحة لإنشاء كائنات مهيأة باسم وصفي.
using System;
class Color
{
public int R, G, B;
private Color(int r, int g, int b) { R = r; G = g; B = b; }
public static Color Red() => new Color(255, 0, 0);
public static Color White() => new Color(255, 255, 255);
}
class Program
{
static void Main()
{
var c = Color.Red();
Console.WriteLine(c.R + "," + c.G + "," + c.B);
}
}لا تستخدم static لمجرد تجنب new
لا تجعل كل شيء static لتجنب إنشاء الكائنات. فإذا كان النوع يمثل شيئًا ذا حالة، فإن الكائنات تعزل تلك الحالة وتحافظ عليها بأمان.
using System;
class Player
{
public string Name;
public int Health = 100;
public void TakeDamage(int d) => Health -= d;
}
class Program
{
static void Main()
{
var p1 = new Player { Name = "A" };
var p2 = new Player { Name = "B" };
p1.TakeDamage(30);
Console.WriteLine(p1.Name + ": " + p1.Health + ", " + p2.Name + ": " + p2.Health);
}
}الملاءمة بين الاثنين
تستخدم أصناف كثيرة الأعضاء static للثوابت أو العدادات المشتركة، وأعضاء instance للبيانات الخاصة بكل كائن. وهذا المزج منسجم تمامًا مع الأسلوب المعتاد.
using System;
class Invoice
{
private static int _seq = 1000;
public readonly int Number;
public decimal Amount;
public Invoice(decimal amount)
{
Number = _seq++;
Amount = amount;
}
}
class Program
{
static void Main()
{
var i1 = new Invoice(50m);
var i2 = new Invoice(75m);
Console.WriteLine(i1.Number + " / " + i2.Number);
}
}مشكلة التزامن
يمكن الوصول إلى الحالة static المشتركة من خيوط متعددة في الوقت نفسه، مما يعرّض البرنامج لحالات التنافس. أما حالة الكائن المحصورة في خيط واحد فهي أكثر أمانًا افتراضيًا.
using System;
class SafeCalc
{
// No shared mutable state -> naturally thread-safe
public static long Factorial(int n)
{
long result = 1;
for (int i = 2; i <= n; i++) result *= i;
return result;
}
}
class Program
{
static void Main()
{
Console.WriteLine(SafeCalc.Factorial(5));
}
}قاعدة عامة بسيطة
Static = سلوك ينتمي إلى النوع ولا يستخدم حالة خاصة بأي كائن. Instance = سلوك يقرأ كائنًا محددًا أو يغيره. وعند الشك، فضّل instance لكل ما يتعلق بالحالة.
using System;
class Temperature
{
public double Celsius; // instance state
public static double ToF(double c) => c * 9 / 5 + 32; // stateless helper
}
class Program
{
static void Main()
{
var t = new Temperature { Celsius = 30 };
Console.WriteLine(Temperature.ToF(t.Celsius));
}
}تجميع المفاهيم
يفصل التصميم الجيد بين المساعدات عديمة الحالة (static) والنماذج ذات الحالة (instance)، مع إبقاء الحالة المشتركة القابلة للتغيير في أضيق نطاق مقصود.
using System;
static class TaxRules
{
public static decimal Apply(decimal amount, decimal rate) => amount + amount * rate;
}
class Sale
{
public decimal Subtotal;
public decimal Total(decimal rate) => TaxRules.Apply(Subtotal, rate);
}
class Program
{
static void Main()
{
var s = new Sale { Subtotal = 100m };
Console.WriteLine(s.Total(0.2m));
}
}اختبار سريع
اختبر مدى فهمك لتصميم static وinstance.
مراجعة
اختر static للمنطق عديم الحالة الذي يعتمد على المدخلات فقط، مثل المساعدات والمصانع والثوابت، واختر instance للسلوك المرتبط بحالة كل كائن. فالحالة static القابلة للتغيير عامة فعليًا، وأصعب في الاختبار، ومعرضة لأخطاء التزامن؛ لذلك اجعل استخدامها محدودًا ومقصودًا.
using System;
static class Util { public static int Sq(int n) => n * n; }
class Box { public int Size; public int Area() => Util.Sq(Size); }
class Program
{
static void Main()
{
var box = new Box { Size = 4 };
Console.WriteLine(box.Area());
}
}الأسئلة الشائعة
هل درس «التصميم الساكن مقابل تصميم النسخ» مجاني؟
نعم — نص درس «التصميم الساكن مقابل تصميم النسخ» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.
ماذا ستتعلم في «التصميم الساكن مقابل تصميم النسخ»؟
قرّروا متى تكون الحالة الساكنة مناسبة تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟
لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «التصميم الساكن مقابل تصميم النسخ»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟
نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الأساليب والحقول الساكنة
- الفئات الساكنة للأدوات المساعدة
- الثوابت والحقول readonly
- التصميم الساكن مقابل تصميم النسخ