design-patterns - شرح - singleton معنى




ما هو سيء للغاية حول المفردات؟ (20)

Singleton ليس عن مثيل واحد!

على عكس الإجابات الأخرى ، لا أريد أن أتحدث عن ما هو خطأ في Singletons ولكن لأظهر لك مدى قوة وهائلة عند استخدامها بشكل صحيح!

  • المشكلة : يمكن أن يكون Singleton تحديًا في بيئة متعددة الخيوط
    الحل : استخدم عملية bootstrap مترابطة واحدة لتهيئة جميع الاعتمادات من المفرد الخاص بك.
  • المشكلة : من الصعب خداع المفردات.
    الحل : استخدام طريقة نمط Factory للسخرية
    MyModel myModel = Factory.inject(MyModel.class); يمكنك تعيين MyModel إلى فئة TestMyModel التي TestMyModel ، في كل مكان عندما يتم حقن TestMyModel ستحصل على TestMyModel.
  • المشكلة : يمكن أن يسبب Singletons الذاكرة الكراث لأنها لا التخلص منها.
    الحل : حسنًا ، تصرفهم! تطبيق رد اتصال في تطبيقك للتخلص بشكل صحيح من مفردات ، يجب إزالة أي بيانات مرتبطة بها وأخيرًا: إزالتها من المصنع.

كما ذكرت في عنوان مفردات ليست حول مثيل واحد.

  • تحسّن Singletons من سهولة القراءة : يمكنك النظر إلى صفك ومعرفة ما هو العنصر المفرد الذي حقنته لمعرفة ما هي تبعياتها.
  • Singletons يحسن الصيانة : بمجرد إزالة التبعية من فئة قمت فقط بحذف بعض حقن singleton ، لا تحتاج للذهاب وتحرير رابط كبير من الطبقات الأخرى التي نقلت التبعية الخاصة بك حول (هذا هو رائحة كريهة بالنسبة لي Jim برغر )
  • يقوم Singletons بتحسين الذاكرة والأداء : عندما يحدث شيء ما في التطبيق الخاص بك ، ويستغرق سلسلة طويلة من الاستدعاءات لتقديمها ، فأنت تضيع الذاكرة والأداء ، باستخدام Singleton تقوم بقص الرجل الأوسط ، وتحسين أدائك واستخدام الذاكرة ( عن طريق تجنب تخصيصات المتغيرات المحلية غير الضرورية).

نمط المفرد هو عضو مدفوع بالكامل في دفتر أنماط صندوق GoF ، لكنه في الآونة الأخيرة يبدو يتيم بدلاً من ذلك من قبل عالم المطورين. ما زلت أستخدم عددًا كبيرًا من المفردات ، خاصةً في صفوف المصانع ، وبينما يجب أن تكون حريصًا بعض الشيء حول مشكلات متعددة المواضيع (مثل أي فئة في الواقع) ، أخفق في معرفة سبب فظاعتها.

يبدو أن Stack Overflow بشكل خاص يفترض أن كل شخص يوافق على أن سينجلتون شرير. لماذا ا؟

يرجى دعم إجاباتك مع " الحقائق أو المراجع أو الخبرة المحددة "


  1. من السهل استخدام (ab) كمتغير عالمي.
  2. الفئات التي تعتمد على المفردات تكون أصعب نسبيا لاختبار الوحدة في عزلة.

Singletons هي أيضا سيئة عندما يتعلق الأمر التجمع . لأنه بعد ذلك ، ليس لديك "singleton واحد" في التطبيق الخاص بك بعد الآن.

خذ بعين الاعتبار الوضع التالي: باعتبارك مطورًا ، يجب عليك إنشاء تطبيق ويب يصل إلى قاعدة بيانات. لضمان أن تتعارض استدعاءات قاعدة البيانات المتزامنة بعضها البعض ، يمكنك إنشاء مؤشر ترابط - حفظ SingletonDao :

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

لذا فأنت على يقين من وجود واحد مفرد في التطبيق الخاص بك وكل قاعدة بيانات تمر عبر هذا واحد وفقط SingletonDao . تبدو بيئة الإنتاج الآن كما يلي:

كل شيء على ما يرام حتى الآن.

الآن ، ضع في اعتبارك أنك تريد إعداد مثيلات متعددة لتطبيق الويب الخاص بك في مجموعة. الآن ، لديك فجأة شيء من هذا القبيل:

هذا يبدو غريبا ، ولكن الآن لديك العديد من المفردات في التطبيق الخاص بك . وهذا هو بالضبط ما لا يفترض أن يكون عليه المفرد: وجود العديد من الأشياء منه. هذا أمر سيء بشكل خاص إذا أردت ، كما هو موضح في هذا المثال ، إجراء مكالمات متزامنة إلى قاعدة بيانات.

بالطبع هذا مثال على الاستخدام السيئ لفرد واحد. ولكن الرسالة من هذا المثال: لا يمكنك الاعتماد على وجود مثيل واحد من مفرد مفرد في التطبيق الخاص بك - خاصة عندما يتعلق الأمر بمجموعات.


أحد الأشياء السيئة في المفردات هو أنه لا يمكنك تمديدها بسهولة. عليك في الأساس أن تبني نوعًا من نمط الديكور أو شيء من هذا القبيل إذا كنت تريد تغيير سلوكها. أيضًا ، إذا كنت تريد في يوم ما أن تكون لديك طرق متعددة لفعل ذلك الشيء ، فقد يكون من المؤلم تغييره ، اعتمادًا على كيفية وضع شفرتك.

هناك شيء واحد يجب ملاحظته ، إذا كنت تستخدم مفردات ، حاول تمريرها إلى من يحتاج إليها بدلاً من السماح لهم بالوصول إليها مباشرة ... وإلا إذا اخترت أن يكون لديك طرق متعددة لفعل الشيء الذي يفعله singleton ، فسيكون بدلاً من ذلك ، من الصعب تغيير كل فئة تضمّن تبعية إذا وصلت إلى المفرد مباشرة.

لذلك في الأساس:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

بدلا من:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

أعتقد أن هذا النوع من الأنماط يسمى حقن التبعية ويعتبر عموما أمرا جيدا.

مثل أي نمط على الرغم من ... التفكير في ذلك ، والنظر في ما إذا كان استخدامه في حالة معينة غير مناسب أو لا ... قواعد يتم كسرها عادة ، وينبغي عدم تطبيق patterns زحى نيلي دون تفكير.


أود أن أتناول النقاط الأربع في الإجابة المقبولة ، على أمل أن يشرح أحدهم سبب أخطائي.

  1. لماذا يتم إخفاء التبعيات في التعليمات البرمجية الخاصة بك سيئة؟ هناك بالفعل عشرات الاعتماديات المخفية (مكالمات C وقت التشغيل ، ومكالمات OS API ، ومكالمات الوظائف العالمية) ، ومن السهل العثور على التبعيات الفردية (البحث عن مثيل ()).

    "جعل شيء عالمي لتجنب عبوره هو رائحة الكود". لماذا لا يمر شيء حولها لتفادي جعله لونًا مفردًا لرائحة الكود؟

    إذا كنت تمرر كائنًا من خلال 10 وظائف في مكدس مكالمات فقط لتجنب المفرد ، فهل هذا أمر رائع؟

  2. مبدأ المسؤولية الفردية: أعتقد أن هذا الأمر غامض بعض الشيء ويعتمد على تعريفك للمسؤولية. سؤال ذو صلة سيكون ، لماذا إضافة هذه "المسؤولية" المحددة إلى مسألة طبقية؟

  3. لماذا يؤدي اقتراب كائن إلى فصل دراسي إلى اقتران أكثر من استخدام ذلك الكائن كصنف منفرد من داخل الصف؟

  4. لماذا تغير المدة التي تدوم فيها الدولة؟ يمكن إنشاء Singletons أو إتلافها يدويًا ، لذلك لا يزال عنصر التحكم موجودًا ، ويمكنك جعل العمر كما هو الحال مع عمر الكائن غير المفرد.

فيما يتعلق باختبارات الوحدة:

  • ليس كل الفئات بحاجة إلى اختبار الوحدة
  • ليس كل الطبقات التي تحتاج إلى اختبار وحدة تحتاج إلى تغيير تنفيذ المفرد
  • إذا كانت تحتاج إلى اختبار الوحدة وتحتاج إلى تغيير التنفيذ ، فإنه من السهل تغيير الفصل الدراسي من استخدام مفردة إلى تمرير مفردة عبرها عبر حقن التبعية.

إن جوابي حول مدى سخرية سنغلتون هو دائمًا ، "يصعب القيام بها بشكل صحيح". العديد من المكونات الأساسية للغات هي مفردات (فئات ، وظائف ، مساحات الأسماء وحتى المشغلين) ، كما هي مكونات في جوانب أخرى من الحوسبة (localhost ، المسار الافتراضي ، نظام الملفات الظاهري ، إلخ) ، وليس عن طريق الصدفة. في حين أنها تسبب المشاكل والإحباط من وقت لآخر ، فإنها يمكن أن تجعل الكثير من الأشياء تعمل بشكل أفضل.

أكبر نقطتي اللولب التي أراها هي: معاملتها كأنها عالمية وفشلت في تحديد إغلاق سينغلتون.

الجميع يتحدث عن سينغلتون كعالم كروي ، لأنها في الأساس. ومع ذلك ، فإن الكثير (للأسف ، ليس كل) من السوء في عالمي يأتي في جوهره من كونه عالميًا ، ولكن كيف تستخدمه. وينطبق نفس الشيء على Singletons. في الواقع أكثر من ذلك مثل "مثيل واحد" حقا لا يعني أن يعني "يمكن الوصول إليها عالميا". إنه ناتج ثانوي طبيعي ، وبالنظر إلى كل ما نعرفه من سوء ، لا ينبغي لنا أن نكون في عجلة من هذا القبيل لاستغلال إمكانية الوصول العالمي. بمجرد أن يرى المبرمجون سينجلتون ، يبدو أنهم يصلون إليه بشكل مباشر من خلال طريقة مثيله. بدلاً من ذلك ، يجب عليك الانتقال إليها تمامًا كما تفعل مع أي كائن آخر. لا ينبغي أن يعلم معظم الرمز أنه يتعامل مع Singleton (اقتران فضفاض ، أليس كذلك؟). إذا وصل عدد صغير من التعليمات البرمجية إلى الكائن كما لو كان عالميًا ، يتم التراجع عن الكثير من الأذى. أوصي بفرضه عن طريق تقييد الوصول إلى وظيفة المثيل.

سياق سينجلتون مهم أيضًا حقًا. السمة المميزة ل Singleton هي أن هناك "واحد فقط" ، ولكن الحقيقة هي أنها "واحدة فقط" داخل نوع معين من السياق / مساحة الاسم. وهي عادةً واحدة من: واحدة لكل مؤشر ترابط ، عملية ، عنوان IP أو مجموعة ، ولكن يمكن أن تكون واحدة لكل معالج ، جهاز ، مساحة اسم / محمولة فئة / أيا كانت ، الشبكة الفرعية ، الإنترنت ، إلخ.

الخطأ الآخر ، الأقل شيوعًا ، هو تجاهل نمط حياة سينجلتون. فقط لأن هناك واحد فقط لا يعني أن سينجلتون هو "القائد دائمًا" و "دائمًا سيكون" ، كما أنه غير مرغوب فيه بشكل عام (الأشياء بدون بداية ونهاية تنتهك جميع أنواع الافتراضات المفيدة في الكود ، ويجب أن تستخدم فقط في الظروف اليائسة.

إذا كنت تجنب هذه الأخطاء ، يمكن أن يكون Singletons لا يزال PITA ، بت هي على استعداد لرؤية الكثير من أسوأ المشاكل يتم تخفيفها بشكل كبير. تخيل Java Singleton ، الذي يتم تعريفه صراحة على أنه مرة واحدة لكل classloader (مما يعني أنه يحتاج إلى سياسة سلامة الخيط) ، مع طرق محددة للإختبار والتدمير ودورة حياة تحدد متى وكيف يتم التذرع بها ، وطبقة "مثيل" الخاصة بها حماية الحزمة بحيث يتم الوصول إليها بشكل عام من خلال كائنات أخرى غير عالمية. لا يزال مصدرا محتملا للمتاعب ، ولكن بالتأكيد أقل بكثير من المتاعب.

للأسف ، بدلاً من تعليم الأمثلة الجيدة عن كيفية عمل Singletons. نحن نعلم أمثلة سيئة ، وندع المبرمجين يهربون منها لفترة من الوقت ، ثم يخبرونهم بأنهم نمط تصميم سيء.


حل Singletons واحد (واحد فقط) المشكلة.

التنافس على الموارد.

إذا كان لديك بعض الموارد ذلك

( 1 ) يمكن أن يكون لها مثيل واحد فقط ، و

( 2 ) تحتاج إلى إدارة هذا المثال الواحد ،

أنت بحاجة إلى مفردة .

لا توجد العديد من الأمثلة. ملف السجل هو ملف كبير. أنت لا تريد مجرد التخلي عن ملف سجل واحد. تريد مسح ومزامنة وإغلاقه بشكل صحيح. هذا مثال لمورد مشترك واحد يجب إدارته.

من النادر أن تحتاج إلى مفردة. السبب في أنهم سيئون هو أنهم يشعرون بأنهم عالميون وهم أعضاء مدفوعون بالكامل في كتاب GoF GoF.

عندما تعتقد أنك بحاجة إلى عالمي ، فأنت على الأرجح تصنع خطأ فادحًا في التصميم.


لدى Misko Hevery ، من Google ، بعض المقالات المثيرة للاهتمام حول هذا الموضوع بالضبط ...

[سنغلتونس] كاذبة مرضية يتلقّى [ ا] إختبار وحدة مثال أنّ يوضّح كيف [سنغلتونس] يستطيع جعلت هو يصعب أن يعرف سلاسل تبعية ويبدأ أو يختبر تطبيق. إنه مثال متطرف إلى حد ما على إساءة الاستخدام ، ولكن النقطة التي يقررها لا تزال صالحة:

Singletons ليست أكثر من دولة عالمية. الدولة العالمية تجعل من الأشياء الخاصة بك حتى يمكن الحصول على سرا من الأشياء التي لم يتم الإعلان عنها في واجهات برمجة التطبيقات الخاصة بهم ، ونتيجة لذلك ، جعل Singletons API الخاص بك في كذبة المرضية.

حيث جعل كل Singletons Gone النقطة التي جعلت من حقنة التبعية من السهل الحصول على أمثلة للمبنيين الذين يحتاجون إليها ، الأمر الذي يخفف من الحاجة الكامنة وراء السيئة Singletons العالمية ، التي شجبت في المقالة الأولى.


ليس من المفارقات نفسها أنها سيئة ولكن نمط تصميم GoF هو. الحجة الوحيدة الحقيقية التي هي صحيحة هي أن نمط تصميم GoF لا يناسب نفسه فيما يتعلق بالتجارب ، خاصة إذا تم إجراء الاختبارات بالتوازي.

يعد استخدام مثيل واحد لفئة ما بنية صحيحة طالما قمت بتطبيق الوسائل التالية في التعليمات البرمجية:

  1. تأكد من أن الفئة التي سيتم استخدامها كصنف منفرد تقوم بتنفيذ واجهة. هذا يسمح للاعشاب أو mocks ليتم تنفيذها باستخدام نفس الواجهة

  2. تأكد من أن سينجلتون آمن بخيط. هذا معين.

  3. يجب أن تكون المفردات بسيطة بطبيعتها وليست معقدة بشكل مفرط.

  4. خلال وقت تشغيل تطبيقك ، حيث يجب أن يتم تمرير الأحرف الفردية إلى كائن معين ، استخدم مصنع الفصل الذي يقوم بإنشاء هذا الكائن وجعل مصنع الفصل ينقل مثيل المفرد إلى الفئة التي تحتاج إليه.

  5. أثناء الاختبار ولضمان السلوك الحتمي ، قم بإنشاء فئة المفرد كطرف منفصل كالفئة الفعلية نفسها أو كعب / محاكاة يقوم بتنفيذ سلوكه وتمريره كما هو في الفئة التي تتطلب ذلك. لا تستخدم عامل الصف الذي يقوم بإنشاء ذلك الكائن تحت الاختبار الذي يحتاج إلى المفرد أثناء الاختبار لأنه سيمرر المثيل العالمي الوحيد منه ، الذي يهزم الهدف.

لقد استخدمنا Singletons في حلولنا مع قدر كبير من النجاح القابل للاختبار لضمان السلوك الحتمي في تدفقات تشغيل الاختبار المتوازية.


معاد صياغه من بريان زر:

  1. وهي تستخدم عادة كمثال عالمي ، لماذا هذا سيئ للغاية؟ لأنك تخفي تبعيات تطبيقك في شفرتك ، بدلاً من تعريضها عبر الواجهات. جعل شيء عالمي لتجنب عبوره هو رائحة الكود .

  2. إنها تنتهك مبدأ المسؤولية الواحدة : بحكم حقيقة أنها تتحكم في خلقها ودورة حياتها.

  3. هم بطبيعتهم يسبب رمز لتكون coupled بإحكام. وهذا يجعل تزويرها تحت الاختبار صعبة بعض الشيء في كثير من الحالات.

  4. أنها تحمل حالة حول مدى عمر التطبيق. ضربة أخرى للاختبار لأنك قد ينتهي بك الأمر إلى وضع تحتاج فيه الاختبارات للاختبار وهو أمر كبير لا لا لاختبارات الوحدة. لماذا ا؟ لأن كل اختبار وحدة يجب أن يكون مستقلاً عن الآخر.


يتم تنفيذ المفرد باستخدام طريقة ثابتة. يتم تجنب الأساليب الثابتة من قبل الأشخاص الذين يقومون بإجراء اختبار الوحدة لأنهم لا يمكن أن يتعرضوا للسخرية أو الاستهزاء. معظم الناس على هذا الموقع هم من كبار مؤيدي اختبار الوحدة. تستخدم الاتفاقية الأكثر قبولًا لتجنب استخدامها نموذج انعكاس نمط التحكم .


انظر ويكيبيديا Singleton_pattern

وهو يعتبر أيضًا نموذجًا مضادًا من قِبل بعض الأشخاص ، الذين يشعرون أنه يستخدم بشكل مفرط ، مما يؤدي إلى فرض قيود غير ضرورية في الحالات التي لا يتطلب فيها مثيل وحيد للفئة. [1] [2] [3] [4]

المراجع (المراجع ذات الصلة فقط من المقال)

  1. ^ أليكس ميلر. أنماط أكره # 1: سينجلتون ، يوليو 2007
  2. ^ سكوت دينسمور. لماذا المفردات هي شريرة ، مايو 2004
  3. ^ ستيف ييغه. [سنغلتونس] اعتبر غبية ، سبتمبر - أيلول 2004
  4. ^ JB Rainsberger، IBM. استخدم مفرداتك بحكمة ، يوليو 2001

الاحتكار هو الشيطان والنغمات الفردية مع الدولة غير القابلة للقراءة / القابلة للتغيير هي المشكلة "الحقيقية" ...

بعد قراءة Singletons كذابون الباثولوجي كما هو مقترح في إجابة جايسون جئت عبر هذا الشغف الصغير الذي يقدم أفضل مثال على كيفية إساءة استخدام الأغنيات الفردية.

العالمية سيئة بسبب:

  • ا. يتسبب في تعارض مساحة الاسم
  • ب. إنه يعرض الدولة بطريقة غير مبررة

عندما يتعلق الأمر Singletons

  • ا. طريقة OO صريحة لدعوتهم ، يمنع النزاعات ، لذلك نشير. ليس مشكلة
  • ب. Singletons دون الدولة (مثل المصانع) ليست مشكلة. يمكن أن يقع Singletons مع الحالة مرة أخرى في فئتين ، تلك التي هي غير قابلة للتغيير أو الكتابة مرة واحدة وقراءة العديد من (ملفات التكوين / الملكية). هذه ليست سيئة. "سينغلتون سينغتونز" ، التي هي نوع من أصحاب المراجع هي تلك التي تتحدث عنها.

في البيان الأخير ، أشار إلى مفهوم المدونة "مفردات" كذابون.

كيف ينطبق هذا على الاحتكار؟

لبدء لعبة الاحتكار ، أولاً:

  • نضع القواعد أولاً حتى يكون الجميع في نفس الصفحة
  • الجميع يحصل على بداية متساوية في بداية اللعبة
  • يتم تقديم مجموعة واحدة فقط من القواعد لتجنب الارتباك
  • لا يُسمح للقواعد بتغييرها طوال اللعبة

الآن ، بالنسبة لأي شخص لم يمارس الاحتكار حقاً ، فإن هذه المعايير مثالية في أحسن الأحوال. من الصعب ابتلاع الهزيمة في الاحتكار ، لأن الاحتكار يدور حول المال ، فإذا خسرت فعليك أن تشاهد بقية اللاعبين وهم ينهون اللعبة ، وعادة ما تكون الخسائر سريعة وسحق. لذا ، فإن القواعد عادة ما تصبح ملتوية في وقت ما لخدمة المصلحة الذاتية لبعض اللاعبين على حساب الآخرين.

لذا فأنت تلعب بالاحتكار مع الأصدقاء ، بوب ، جو ، وإد. أنت تبني إمبراطوريتك بسرعة وتستهلك حصة سوقية بمعدل أسي. يضعف خصومك وتبدأ رائحة الدم (المجازي). وضع صديقك بوب جميع أمواله في الدخول في شبكة متشابكة مثل العديد من العقارات ذات القيمة المنخفضة قدر الإمكان ولكن لا يحصل على عائد مرتفع على الاستثمار بالطريقة التي توقعها. بوب ، كما ضربة حظ سيئ ، يهبط على الممشى الخاص بك ويستأصل من اللعبة.

الآن تذهب اللعبة من النرد المتداول ودية لرجال الأعمال خطيرة. لقد جعل بوب مثال الفشل ، ولا يريد جو إد أن ينتهي بهم الأمر مثل "ذلك الرجل". لذا ، كونك اللاعب الرئيسي ، فجأة ، أصبح العدو. يبدأ كل من جو و إد بالقيام بالتجارة تحت الطاولة ، وحقن الأموال من الخلف ، ومقايضة المنزل بأقل من قيمتها ، وعموما أي شيء لإضعافك كلاعب حتى يرتقي أحدهما إلى القمة.

ثم ، بدلاً من فوز أحدهم ، تبدأ العملية في كل مكان. فجأة ، تصبح مجموعة محدودة من القواعد هدفًا متحركًا ، وتتحول اللعبة إلى نوع من التفاعلات الاجتماعية التي ستشكل أساس كل برنامج تلفزيوني واقعي عالي الجودة منذ فيلم Survivor. لماذا ، لأن القواعد تتغير ولا يوجد إجماع حول كيفية / لماذا / ما من المفترض تمثيله ، والأهم من ذلك ، أنه لا يوجد شخص واحد يتخذ القرارات. كل لاعب في اللعبة ، عند هذه النقطة ، يجعل قواعده والفوضى الخاصة به تترتب على ذلك حتى يكون لاعبين اثنين متعبين للغاية من أجل الحفاظ على التمرد والتخلي ببطء.

لذا ، إذا كان كتاب قواعد اللعبة يمثل بدقة مفردة ، فإن كتاب القواعد الاحتكارية سيكون مثالاً على سوء المعاملة.

كيف ينطبق هذا على البرمجة؟

بغض النظر عن جميع المسائل الواضحة للسلامة والمزامنة التي تحدثها المفردات القابلة للتغيير ... إذا كان لديك مجموعة واحدة من البيانات ، فمن الممكن قراءتها / التلاعب بها من قبل مصادر مختلفة متعددة في نفس الوقت وتوجد خلال فترة تنفيذ التطبيق ، ربما يكون الوقت مناسبًا للتراجع وسؤال "هل أستخدم النوع الصحيح من بنية البيانات هنا".

شخصيا ، لقد رأيت مبرمج الاعتداء على singleton باستخدامه كنوع من تخزين قاعدة البيانات المترابطة الموضوع داخل تطبيق. بعد أن عملت على الشفرة مباشرة ، يمكنني أن أشهد أنها كانت بطيئة (بسبب كل أقفال الخيط اللازمة لجعلها آمنة من ناحية الصفحات) وكابوس للعمل عليها (بسبب الطبيعة المتقطعة / المتقطعة لأخطاء المزامنة) ، يكاد يكون من المستحيل اختبارها تحت ظروف "الإنتاج". بالتأكيد ، كان من الممكن تطوير نظام باستخدام الاستطلاعات / الإشارات للتغلب على بعض مشكلات الأداء ولكن ذلك لن يحل المشكلات مع الاختبار ، ولماذا تهتم عندما تكون قاعدة البيانات "الحقيقية" قادرة بالفعل على تحقيق الوظيفة نفسها في إطار أكثر قوة / بطريقة قابلة للتطوير.

إن Singleton هو خيار فقط إذا كنت بحاجة إلى ما يوفره singleton. مثيل للقراءة فقط للكتابة واحد للكائن. يجب أن تتالي نفس القاعدة إلى خصائص / أعضاء الكائن أيضًا.


A pattern emerges when several people (or teams) arrives at similar or identical solutions. A lot of people still use singletons in their original form or using factory templates (good discussion in Alexandrescu's Modern C++ Design). Concurrency and difficulty in managing the lifetime of the object are the main obstacles, with the former easily managed as you suggest.

Like all choices, Singleton has its fair share of ups and downs. I think they can be used in moderation, especially for objects that survive the application life span. The fact that they resemble (and probably are) globals have presumably set off the purists.


Firstly a class and its collaborators should firstly perform their intended purpose rather than focusing on deoendents. Lifecycle management (when instances are creared snd when they go out of scope) should not be part of the cladses responsibility. The accepted best practice for this is to craft or configure a new component to manage dependencies using dependency injection.

Often software gets more complicated it makes sense to have multiple independent instances of the "singleton" class with different state. Committing code to simply grab the singleton is wrong in such cases. Using Singleton.getInstance() might be ok for small simple systems but it doesn't work / scale when one might need a different instance of the same class.

No class should be thought of as a singleton but rather that should be an aplication of it's usage or how it is used to configure dependents. For a quick and nasty this does not matter- just luke hardcoding say file paths does not matter but for bigger applications such dependencies need to be factored out and managed in more appropriate way using DI.

The problems that singleton cause in testing is a symptom of their hard coded single usage case/environment. The test suite and the many tests are each individual and separate something that is not compatible with hardcoding a singleton.


Here is one more thing about singletons which nobody said yet.

In most cases "singletonity" is a detail of implementation for some class rather than characteristic of its interface. Inversion of Control Container may hide this characteristic from class users; you just need to mark your class as a singleton (with @Singleton annotation in Java for example) and that's it; IoCC will do the rest. You don't need to provide global access to your singleton instance because the access is already managed by IoCC. Thus there is nothing wrong with IoC Singletons.

GoF Singletons in opposite to IoC Singletons are supposed to expose "singletonity" in the interface through getInstance() method, and so that they suffer from everything said above.


Singleton is a pattern and can be used or abused just like any other tool.

The bad part of a singleton is generally the user (or should I say the inappropriate use of a singleton for things it is not designed to do). The biggest offender is using a singleton as a fake global variable.


Singletons are NOT bad. It's only bad when you make something globally unique that isn't globally unique.

However, there are "application scope services" (think about a messaging system that makes components interact) - this CALLS for a singleton, a "MessageQueue" - class that has a method "SendMessage(...)".

You can then do the following from all over the place:

MessageQueue.Current.SendMessage(new MailArrivedMessage(...));

And, of course, do:

MessageQueue.Current.RegisterReceiver(this);

in classes that implement IMessageReceiver.


There is nothing inherently wrong with the pattern, assuming it is being used for some aspect of your model which is truly single.

I believe the backlash is due to its overuse which, in turn, is due to the fact that it's the easiest pattern to understand and implement.


Too many people put objects which are not thread safe in a singleton pattern. I've seen examples of a DataContext ( LINQ to SQL ) done in a singleton pattern, despite the fact that the DataContext is not thread safe and is purely a unit-of-work object.





singleton