طريقتان لتنفيذ وضع Singleton في دلفي
haozi
الملخص توضح هذه المقالة تطبيقي دلفي لوضع Singleton وتقوم بإجراء تحليل مقارن.
نمط تصميم الكلمات الرئيسية، Singleton
يعد نمط Singleton نمط تصميم مفيدًا جدًا. والغرض منه هو ببساطة إنشاء مثيل لفئة وتوفير نقطة وصول عالمية إليها. تعمل المتغيرات العامة على تسهيل الوصول إلى الكائن، ولكنها لا تمنعك من إنشاء كائنات متعددة. الغرض من النمط المفرد هو التأكد من وجود مثيل واحد فقط خلال دورة حياة البرنامج.
انظر إلى الكود أدناه:
الإجراء TForm1.Button1Click(Sender: TObject);
فار ls1 : TSingleton l
S2: TSingleton؛
يبدأ
حاول lS1 := TSingleton.Create; //// اتصل بمنشئ الفصل
lS2 := TSingleton.Create; //// اتصل بمنشئ الفصل
//// ...رمز آخر
أخيراً
lS1.Free; //// حرر الكائن
lS2.Free; //// حرر الكائن
نهاية؛
نهاية؛
في التعليمات البرمجية أعلاه، يتم إنشاء فئة TSingleton عندما يتم استدعاء وظيفة الإنشاء للمرة الأولى، ويشير lS1 إلى عنوان كائن تخزين الذاكرة. عند استدعاء وظيفة TSingleton.Create للمرة الثانية، يتم إعادة كائن TSingleton -تم إنشاء مثيل لـ lS2 إلى عنوان آخر مخصص للذاكرة. نمط Singleton هو السماح للفصل نفسه أن يكون مسؤولاً عن حفظ مثيله الوحيد.
في الكود أعلاه، عند إنشاء ls2، فإنه يشير أيضًا إلى الكائن المشار إليه بواسطة ls1 (أي أنه تم تخصيص نفس عنوان الذاكرة له). وبالمثل، يجب علينا منع تحرير الذاكرة عند تحرير ls1، لأن الملف الفردي تتم الإشارة إلى الكائن أيضًا بواسطة ls2. وهذا يضمن وجود مثيل فئة واحد فقط خلال دورة حياة البرنامج.
يستخدم نموذج التعليمات البرمجية لـ C++ في "نمط التصميم" متغيرات الأعضاء الثابتة لـ C++ لحفظ المثيلات ويستخدم وظائف المنشئ المحمية. على أية حال، بما أنه لا يوجد متغيرات أعضاء ثابتة في دلفي، لا يمكن استخدام طريقة مثال الوضع المفرد هذا كما هي. أدناه نقوم بتحليل عدة طرق لـ DELPHI لتنفيذ وضع Singleton.
واحد. تعتمد الطريقة على تجاوز وظيفتين افتراضيتين لـ Tobject
وظيفة الفئة NewInstance: TObject;
الإجراء FreeInstance الظاهري؛
تعد وظيفة NewInstance مسؤولة عن تخصيص الذاكرة للكائن عند إنشاء كائن الفئة، بينما يقوم FreeInstance بتحرير الذاكرة على العكس من ذلك.
.
يتم استدعاء الأول عند إنشاء الكائن، ويتم استدعاء الأخير عند تدمير الكائن.
نحن نستخدم متغيرين عالميين للاحتفاظ بالكائن المفرد والعدد المرجعي للكائن.
varInstance: TSingleton = nil;
RefCount : عدد صحيح = 0؛
وحدات فئة TSingleton:
////--------------------------------------------- -- --------------------------
////
وحدة uSingleton؛
واجهة
يكتب
TSingleton = فئة (TObject)
عام
وظيفة الفئة NewInstance: TObject;
تجاوز الإجراء FreeInstance؛ //// تجاوز وظيفة الفئة الأساسية
دالة الفصل RefCount: عدد صحيح؛//// إرجاع العدد المرجعي الحالي
نهاية؛
//// إعلان المتغيرات العالمية
فار
المثيل: TSingleton = nil;
RefCount: عدد صحيح = 0؛
تطبيق
{سينجلتون}
الإجراء TSingleton.FreeInstance؛
يبدأ
Dec( RefCount );////تقليل عدد المراجع
إذا (RefCount = 0) إذن //// هل هو 0، إذا كان الأمر كذلك، حرر الذاكرة
يبدأ
المثيل := لا شيء؛
//// قم بتحرير المتغيرات الخاصة للفئة المفردة
////…
FreeInstance الموروثة؛
نهاية؛
نهاية؛
دالة الفئة TSingleton.NewInstance: TObject;
يبدأ
إذا ( لم يتم تعيينه (مثيل ) ) إذن
يبدأ
المثيل := TSingleton(inherited NewInstance);
////مثال على تهيئة المتغيرات الخاصة:
//// Instance.VariableName := Value;
نهاية؛
النتيجة := مثيل؛
شركة (RefCount)؛
نهاية؛
دالة الفئة TSingleton.RefCount: عدد صحيح؛
يبدأ
النتيجة := RefCount;
نهاية؛
نهاية.
////--------------------------------------------- -- --------------------------
////
عندما يتم استدعاء مُنشئ TSingleton، سيتم استدعاء وظيفة التجاوز NewInstance الخاصة بنا، وسوف تقوم NewInstance بتخصيص الذاكرة وإعادتها إلى المُنشئ. وبهذه الطريقة، من خلال وظيفة التجاوز NewInstance، نضمن أن وظيفة الإنشاء يمكنها فقط إنشاء كائن TSingleton. (بغض النظر عن عدد المرات التي يتم استدعاؤها) فإن الإنشاء يُرجع فقط عنوان الذاكرة المخصص لأول مرة). في نفس الوقت يحتفظ المتغير RefCount بعدد المراجع التي لدينا للكائن.
دعونا نلقي نظرة على رمز الاختبار
الإجراء TForm1.Button1Click(Sender: TObject);
فار
LS1، LS2: TSingleton؛
Ob1، Ob2: الكائن؛
يبدأ
lS1 := TSingleton.Create;
ShowMessage(IntToStr(RefCount)); //// Ref_Count = 1
lS2 := TSingleton.Create;
ShowMessage(IntToStr(RefCount)); //// Ref_Count = 2
Ob1 := TObject.Create;
Ob2 := Tobject.Create;
إذا كان ls1 = ls2 إذن
ShowMessage('العناوين متساوية') //// lS1 = lS2
آخر
ShowMessage('العناوين غير متساوية');
إذا Ob1 = Ob2 ثم
ShowMessage('العناوين متساوية')
آخر
ShowMessage('العناوين غير متساوية'); //// Ob1 <> Ob2
نهاية؛
عندما يستدعي البرنامج المدمر (أي عند استدعاء الدالة المجانية)، سيقوم المدمر باستدعاء وظيفة FreeInstance لتحرير الذاكرة المخصصة بواسطة المُنشئ. تضمن وظيفة FreeInstance الخاصة بالتجاوز تحرير ذاكرة كائن الوضع المفرد فقط عندما يصل العدد المرجعي إلى الصفر.
هنا هو رمز الاختبار لدينا:
فار
LS1: تسينجلتون؛
LS2: تسينجلتون؛
يبدأ
يحاول
lS1 := TSingleton.Create; //// اتصل بمنشئ الفصل
lS2 := TSingleton.Create; //// اتصل بمنشئ الفصل
//// ...رمز آخر
أخيراً
lS1.Free; //// هنا سوف نقوم أولاً باستدعاء FreeInstance المحدد بواسطة التجاوز الخاص بنا،
//// نظرًا لأن RefCount هو 1 بعد التناقص بمقدار 1 في هذا الوقت، لم يتم تحرير الكائن المفرد.
lS2.Free; ////dec(RefCount)= 0 يطلق الكائن المفرد
نهاية؛
نهاية؛
تعد طريقة تنفيذ النمط الفردي المذكورة أعلاه طريقة جيدة لإدراك أن الفئة نفسها مسؤولة عن حفظ مثيلها الفريد (من خلال اعتراض الطلب لإنشاء كائن جديد - راجع "أنماط التصميم". وليس لديها قيود خاصة على الاستخدام من فئة TSingleton - — يمكن للمبرمجين استدعاء وظائف الإنشاء والتحرير حسب الرغبة.
عيب هذا الوضع هو أنه لا يمكن وراثة فئة TSingleton كفئة أصل لإنشاء فئات فرعية. إذا أدى الوراثة إلى إنشاء فئتين فرعيتين، فسيتم إنشاء كائن واحد فقط أثناء الإنشاء.
الإجراء TForm1.Button1Click(Sender: TObject);
فار
LS1: الفئة الفرعية الأولى؛
LS2: الفئة الفرعية الثانية؛
يبدأ
lS1:= فئة فرعية 1.إنشاء؛
lS2 := فئة فرعية 2.إنشاء //// لن يتم إنشاء فئة فرعية 2، وسيشير lS2 إلى الذاكرة المشار إليها بواسطة lS1،
//// أي ls1 = lS2end;
اثنين. تنفيذ دلفي للمثال في "أنماط التصميم"
مثال تنفيذ "نمط التصميم" هو التحكم في مثيل كائن واحد فقط من خلال وظيفة منشئ خاص. ومع ذلك، فإن تطبيق تعليمات برمجية C++ المحدد لا يوضح كيفية تحرير الكائن. لا يمكن خصخصة وظيفة الإنشاء في دلفي، لقد قمنا بتحديد وظيفة جديدة لتحل محل وظيفة الإنشاء وحماية وظيفة الإنشاء للفئة الأصلية. الرمز هو كما يلي
:
////--------------------------------------------- -- --------------------------
////
Unit uSingletonUnit;
واجهة
الاستخدامات
الطبقات، سيسوتيلس؛
يكتب
TCSingleton = class(TComponent) //// موروث من فئة Tcomponent.
خاص
المُنشئ CreateInstance(AOwner: TComponent);
//// بهذه الطريقة، سيتم تدمير كائن فئة TCSingleton مع المالك (المالك مسؤول عن تدمير كائن TCSingleton)
عام
إنشاء المنشئ (AOwner: TComponent)؛
مثيل وظيفة الفئة (AOwner: TComponent): TCSingleton؛
نهاية؛
فار
gCSingleton: TCSingleton; //// المتغيرات العامة
تطبيق
{TCSingleton}
منشئ TCSingleton.Create(AOwner: TComponent);
يبدأ
//// حماية وظيفة إنشاء الوظيفة
رفع Exception.CreateFmt('الوصول إلى الفئة %s من خلال المثيل فقط'،
[اسم الفئة])؛
نهاية؛
المنشئ TCSingleton.CreateInstance(AOwner: TComponent);
يبدأ
//// المنشئ المحدد حديثًا هو خاص
ورثت إنشاء (AOwner)؛
نهاية؛
وظيفة الفئة TCSingleton.Instance(AOwner: TComponent): TCSingleton;
يبدأ
إذا لم يتم تعيينه (gCSingleton) إذن
gCSingleton := TCSingleton.CreateInstance(AOwner);
النتيجة := gCSingleton;
نهاية؛
نهاية.
////--------------------------------------------- -- ----------------------------/
/
أثناء استخدام فئة التنفيذ المذكورة أعلاه، لا يحتاج المبرمجون إلى التفكير في تدمير كائنات الوضع المفرد. لا يمكن استدعاء إنشاء، يجب عليك استدعاء وظيفة المثيل للحصول على مثيل للكائن، وتمرير المالك المفرد كمعلمة إلى الوظيفة. يمكن وراثة طريقة التنفيذ هذه كفئة أساسية واستخدامها في نمط الحالة الفردي (انظر المرجع 4) لتحقيق تعدد الأشكال في وقت التنفيذ.
ثلاثة. خاتمة
يمكن أيضًا العثور على تطبيق دلفي لوضع Singleton على الإنترنت. هناك طريقتان للتنفيذ في هذه المقالة
الأكثر شيوعا وبسيطة. وفي الوقت نفسه، فإن أفكار الطرق الأخرى مشابهة جدًا للطريقتين المذكورتين أعلاه.