في هندسة البرمجيات، يعد النمط المفرد أو الاحادي (بالإنجليزية: singleton pattern) نمط تصميم برامجيات يقيد إنشاء مثيل برمجي لصنف واحد بمثيل «احادي». مفيد عندما تكون هناك حاجة إلى كائن واحد بالضبط لتنسيق الإجراءات عبر النظام. المصطلح يأتي من المفهوم الرياضي للأحادي.
يعتبر النقاد أن المفرد هو نمط مضاد لأنه يستخدم بشكل متكرر في السيناريوهات حيث لا يكون مفيدًا، ويقدم قيودًا غير ضرورية في المواقف التي لا يكون فيها مثيل برمجي وحيد للصنف مطلوبًا بالفعل، ويدخل الحالة البرمجية العامة في التطبيق.[1][2][3]
يُعد نمط التصميم المفرد[4] أحد أنماط التصميم الثلاثة والعشرون المعروفة باسم "عصابة الأربعة" التي تصف كيفية حل مشكلات التصميم المتكررة لتصميم برامج كائنية التوجه قابلة لإعادة الاستخدام ومرنة، أي الكائنات التي يسهل فيها التنفيذ البرمجي والتغيير والاختبار وإعادة الاستخدام.
يحل نمط التصميم الفردي مشاكل مثل:[5]
يصف نمط التصميم الفردي كيفية حل هذه المشاكل:
()getInstance
) تقوم بإرجاع برمجي (بالإنجليزية: returns) المثيل الاحادي للصنف.الفكرة الرئيسية في هذا النمط هي جعل الصنف نفسه مسؤول عن التحكم في استنساخه (التي يتم استنساخه مرة واحدة فقط). يضمن المُنشئ المخفي (المُعلن بوصول خاص (بالإنجليزية: declared private)) أنه لا يمكن إنشاء مثيل الصنف على الإطلاق من خارج الصنف. يمكن الوصول إلى العملية الثابتة العامة البرمجية بسهولة باستخدام اسم الصنف واسم العملية (()Singleton.getInstance
).
تنفيذ النمط المفرد يجب أن يتبع التالي:
عادة، يتم ذلك عن طريق:
يتم تخزين المثيل عادة كمتغير ثابت خاص برمجياً؛ يتم إنشاء المثيل عند تهيئة المتغير، في مرحلة ما قبل استدعاء الدالة الثابتة برمجياً لأول مرة. فيما يلي نموذج تنفيذ مكتوب بلغة جافا.
public class Coin {
private static final int ADD_MORE_COIN = 10;
private int coin;
private static Coin instance = new Coin(); // تحميل باسرع وقت ممكن لمثيل احادي
private Coin(){
// private
// وضع وصول خاص لمنع اي شخص من انشاء مثيل برمجي
}
public static Coin getInstance(){
return instance;
}
public int getCoin(){
return coin;
}
public void addMoreCoin(){
coin += ADD_MORE_COIN;
}
public void deductCoin(){
coin--;
}
}
public final class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
قد ينفذ نمط الاحادي التهيئة البطيئة (بالإنجليزية: Lazy initialization)، حيث يتم إنشاء المثيل عندما يتم استدعاء الطريقة الثابتة برمجياً لأول مرة. إذا كان من الممكن استدعاء الطريقة الثابتة من خيوط متعددة (بالإنجليزية: Multiple threads) بشكل متزامن، فقد يلزم اتخاذ تدابير لمنع ظروف السباق التي قد تؤدي إلى إنشاء مثيلات برمجية متعددة من الصنف. ما يلي هو تنفيذ نموذج سلامة الخيوط (بالإنجليزية: thread-safe)، باستخدام التهيئة البطيئة مع القفل المزدوج (بالإنجليزية: double-checked locking)، المكتوب بلغة جافا.
public final class Singleton {
private static volatile Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
public sealed class Singleton {
private static readonly Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton Instance {
get {
return INSTANCE;
}
}
}
في سي شارب، يمكنك أيضًا استخدام أصناف ثابتة لإنشاء أنماط احادية، حيث يكون الصنف نفسه هو نمط احادي.
public static class Singleton {
private static readonly MyOtherClass INSTANCE = new MyOtherClass();
public static MyOtherClass Instance {
get {
return INSTANCE;
}
}
}
class Singleton {
static Singleton _instance;
static Singleton get instance => _instance ?? Singleton._();
Singleton._() => _instance = this;
}
class Singleton {
private static $instance = null;
private function __construct(){}
public static function getInstance(): self
{
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
الكلمة المفتاحية لكائن كوتلن object يعلن برمجياً عن صنف من النمط الاحادي.
object Coin{
// wrong example.
private var coin: Int = 0
fun getCoin():Int{
return coin
}
fun addCoin(){
coin += 10
}
fun deductCoin(){
coin--
}
}
GetInstance الدالة عبارة عن تنفيذ خيوط حاسوبي آمن للنمط البرمجي الاحادي.
unit SingletonPattern;
interface
type
TTest = class sealed
strict private
FCreationTime: TDateTime;
public
constructor Create;
property CreationTime: TDateTime read FCreationTime;
end;
function GetInstance: TTest;
implementation
uses
SysUtils
, SyncObjs
;
var
FCriticalSection: TCriticalSection;
FInstance: TTest;
function GetInstance: TTest;
begin
FCriticalSection.Acquire;
try
if not Assigned(FInstance) then
FInstance := TTest.Create;
Result := FInstance;
finally
FCriticalSection.Release;
end;
end;
constructor TTest.Create;
begin
inherited Create;
FCreationTime := Now;
end;
initialization
FCriticalSection := TCriticalSection.Create;
finalization
FreeAndNil(FCriticalSection);
end.
طريقة الاستخدام هي كالتالي:
procedure TForm3.btnCreateInstanceClick(Sender: TObject);
var
i: integer;
begin
for i := 0 to 5 do
ShowMessage(DateTimeToStr(GetInstance.CreationTime));
end;
مَسرد المفردات وفق أقسام المقالة | |
المقدمة | |
نمط تصميم برامجيات | software design pattern |
إنشاء مثيل برمجي | instantiation |
لصنف | class |
«احادي» | single |
احادي | singleton |
نمط مضاد | anti-pattern |
الحالة البرمجية العامة | Global variables |
عصابة الأربعة (الأنماط البرمجية) | "Gang of Four" design patterns |
تنفيذ برمجي | implement |
منشىْ الصنف | the constructor of the class |
تعريف برمجي | Define |
خاصية الثبات بالنسبة للصنف | static |
خاصية حالة الوصول عامة | public |
مثيل احادي للصنف | sole instance of the class |
خاصية حالة الوصول الخاص | private |
صنف من النمط الاحادي | singleton class |
الكلمة المفتاحية لكائن كوتلن | Kotlin object keyword |
يعلن برمجياً | declares |
تنفيذ خيوط حاسوبي أمن | thread safe implementation |
فريباسكال | Free Pascal |
للمصنع المجرد | abstract factory |
طريقة المصنع | factory method |
أنماط النموذج الأولي | prototype |
الانماط الاحادية | Singletons |
واجهة | Facade |
كائنات الحالة | State objects |
المتغيرات العامة | global variables |
التخصيص والتهيئة | lazy allocation and initialization |
مساحات الأسماء المتداخلة | nested namespaces |
موادر برمجية | resources |
التنفيذ | Implementation |
الوصول العام | global access |
المثيل البرمجي | instance |
بنائات | constructors |
تهيئة بطيئة | Lazy initialization |
{{استشهاد بكتاب}}
: صيانة الاستشهاد: أسماء متعددة: قائمة المؤلفين (link)