يعد النمط المفرد أحد أنماط التصميم الثلاثة والعشرين، وهو نمط تصميم بسيط نسبيًا، والغرض منه هو إرجاع نفس الكائن بغض النظر عن عدد مرات استدعائه.
وهو مقسم إلى بنيتين، أحدهما أسلوب الرجل الكسول والآخر أسلوب الرجل الجائع، ولكل منهما مميزاته وعيوبه. لنبدأ بأسلوب الرجل الجائع.
public class Single { public static Single = new Single(); { } public Single getInstance() { return Single } }
يمكن أن نرى من البرنامج أعلاه أنه على الرغم من تحقيق هدفنا المتمثل في تحميل نفس الكائن، إلا أنه سيتم إنشاء كائن واحد عند تحميل البرنامج. عندما تحتوي هذه الفئة على العديد من هذه الأساليب، فقد لا نستخدمها في معظم الأحيان في هذا الكائن سوف يسبب مضيعة للذاكرة. لذلك ظهر نمط المفرد البطيء، والكود هو كما يلي:
public class Single { // static Single = null public Single();
بهذه الطريقة، سيكون الكائن جديدًا فقط عندما نسميه بالفعل، ولكن هناك مشكلة في ذلك.
عندما يتم استدعاء الجزء الثاني من التعليمات البرمجية أعلاه بواسطة خيطين عند تحميله لأول مرة، سيتم إنشاء كائنين مختلفين، لذلك فإن الخيط غير آمن في هذا الوقت، ستفكر في إضافة رمز القفل بعد القفل على النحو التالي:
public class Single { public static Single = null; public Single getInstance() { if (single == null) { Single = new Single() } return Single;
يؤدي هذا إلى تحقيق أمان الخيط، ولكن عندما تحتاج طريقة القفل إلى تنفيذ الكثير من الأشياء، فإن استدعاء هذه الطريقة سيستغرق وقتًا طويلاً، وهو أمر قاتل للخادم، لأنه إذا استمر الخيط في استدعاء هذه الطريقة، فلا توجد طريقة لضبطه المواضيع الأخرى، وسيتم حظر الخادم ثم الكود الذي تمت ترقيته هو كما يلي:
public class Single {priate static Single = null; public Single() { } public Single getInstance() { if (single == null) { syncr (Single.class) { Single = new Single() } } return Single; } }
بعد المراقبة الدقيقة، وجدت أنه لا يوجد قفل بهذه الطريقة. عندما يصل خيطان إلى طريقة getInstance () في حالة الحكم لأول مرة، يجب حظر أحدهما بعد اكتمال تنفيذ الآخر، وسيتم حظر الخيط لم يعد لتحديد ما إذا كان فارغًا أم لا، سيتم إنشاء كائن بهذه الطريقة، ثم تتم ترقيته، ويكون الكود الناتج كما يلي:
فئة عامة مفردة { مفردة ثابتة خاصة = خالية خاصة مفردة () { } عامة مفردة getInstance () { إذا (مفردة == خالية) { متزامنة (Single.class) { إذا (مفردة == خالية) { مفردة = مفردة جديدة (); } } } إرجاع منفرد } }
بهذه الطريقة، لن تحدث المشكلة المذكورة أعلاه، وسيتم قفلها مرة واحدة فقط، لأنه عند تنفيذ الطريقة للمرة الثانية، سيتم تخطي حكم if وسيتم إرجاع المفرد مباشرة ولن يتم قفله مرة أخرى وستكون كفاءة التنفيذ عالية جدًا.
ولكن على الرغم من ذلك، لا تزال هناك مشكلة، لأننا لا نستطيع التأكد مما إذا كان الكائن قد تم تعيين قيمة له في الذاكرة أولاً أم أنه تم إنشاء الكائن أولاً، لذلك قد يحصل البرنامج الثاني على كائن نصف مهيأ في jdk1 يمكننا استخدام الكلمة الأساسية المتقلبة لتجنب هذا الموقف، الكود كما يلي:
فئة عامة مفردة { مفردة ثابتة خاصة = فارغة؛ خاصة مفردة () { } عامة مفردة getInstance () { if (single == null) { syncr (Single.class) { if (single == null) { Single = new واحد ()؛ } } } إرجاع واحد؛
لكن نادرًا ما يتم استخدام هذا الوضع، أنا هنا فقط للتعلم، هيهي