Orang lajang seperti komunisme: keduanya terdengar hebat di atas kertas, tetapi pada praktiknya meledak dengan masalah.
Pola singleton memberikan penekanan yang tidak proporsional pada kemudahan mengakses objek. Ini sepenuhnya menghindari konteks dengan mengharuskan setiap konsumen menggunakan objek dengan cakupan AppDomain, tanpa meninggalkan opsi untuk berbagai implementasi. Ini menyematkan pengetahuan infrastruktur di kelas Anda (panggilan ke GetInstance()
) sambil menambahkan tepat nol kekuatan ekspresif. Ini sebenarnya mengurangi kekuatan ekspresif Anda, karena Anda tidak dapat mengubah implementasi yang digunakan oleh satu kelas tanpa mengubahnya untuk semuanya . Anda tidak bisa menambahkan fungsionalitas satu kali.
Juga, ketika kelas Foo
bergantung pada Logger.GetInstance()
, Foo
secara efektif menyembunyikan ketergantungannya dari konsumen. Ini berarti Anda tidak dapat sepenuhnya memahami Foo
atau menggunakannya dengan percaya diri kecuali Anda membaca sumbernya dan menemukan fakta bahwa itu bergantung Logger
. Jika Anda tidak memiliki sumbernya, itu membatasi seberapa baik Anda dapat memahami dan secara efektif menggunakan kode yang Anda andalkan.
Pola tunggal, seperti yang diterapkan dengan properti / metode statis, tidak lebih dari sekadar peretasan dalam mengimplementasikan infrastruktur. Ini membatasi Anda dalam banyak cara sambil tidak menawarkan manfaat yang terlihat atas alternatifnya. Anda dapat menggunakannya sesuka Anda, tetapi karena ada alternatif yang layak yang mempromosikan desain yang lebih baik, ini tidak boleh menjadi praktik yang direkomendasikan.
Yang lain telah menjelaskan dengan sangat baik masalah dengan lajang secara umum. Saya hanya ingin menambahkan catatan tentang kasus spesifik Logger. Saya setuju dengan Anda bahwa biasanya bukan masalah untuk mengakses Logger (atau root logger, tepatnya) sebagai seorang tunggal, melalui statik
getInstance()
ataugetRootLogger()
metode. (kecuali jika Anda ingin melihat apa yang dicatat oleh kelas yang Anda uji - tetapi dalam pengalaman saya, saya hampir tidak dapat mengingat kasus seperti itu di mana hal ini diperlukan. Kemudian lagi, bagi orang lain ini mungkin menjadi masalah yang lebih mendesak).Biasanya IMO logger tunggal tidak perlu dikhawatirkan, karena tidak berisi status apa pun yang relevan dengan kelas yang Anda uji. Artinya, status logger (dan kemungkinan perubahannya) tidak berpengaruh apa pun pada status kelas yang diuji. Jadi itu tidak membuat pengujian unit Anda lebih sulit.
Alternatifnya adalah memasukkan logger melalui konstruktor, ke (hampir) setiap kelas dalam aplikasi Anda. Untuk konsistensi antarmuka, itu harus dimasukkan bahkan jika kelas yang dimaksud tidak mencatat apa pun saat ini - alternatifnya adalah ketika Anda menemukan di beberapa titik bahwa sekarang Anda perlu mencatat sesuatu dari kelas ini, Anda memerlukan pencatat, jadi Anda perlu menambahkan parameter konstruktor untuk DI, melanggar semua kode klien. Saya tidak menyukai kedua opsi ini, dan saya merasa bahwa menggunakan DI untuk logging hanya akan mempersulit hidup saya untuk mematuhi aturan teoretis, tanpa manfaat konkret.
Jadi intinya adalah: kelas yang digunakan (hampir) secara universal, tetapi tidak berisi status yang relevan dengan aplikasi Anda, dapat dengan aman diimplementasikan sebagai Singleton .
sumber
Ini sebagian besar, tetapi tidak seluruhnya tentang tes. Singlet populer karena mudah dikonsumsi, tetapi ada sejumlah kerugian bagi lajang.
DI memberi Anda konsumsi kelas dependen yang mudah - cukup taruh di argumen konstruktor, dan sistem menyediakannya untuk Anda - sambil memberi Anda fleksibilitas pengujian dan konstruksi.
sumber
Tentang satu-satunya saat Anda harus menggunakan Singleton daripada Dependency Injection adalah jika Singleton mewakili nilai yang tidak dapat diubah, seperti List.Empty atau sejenisnya (dengan asumsi daftar yang tidak dapat diubah).
Pemeriksaan usus untuk Singleton harus "apakah saya akan baik-baik saja jika ini adalah variabel global, bukan Singleton?" Jika tidak, Anda menggunakan pola Singleton untuk menjelaskan variabel global, dan harus mempertimbangkan pendekatan yang berbeda.
sumber
Baru saja memeriksa artikel Monostate - ini adalah alternatif bagus untuk Singleton, tetapi memiliki beberapa properti yang aneh:
Bukankah ini menakutkan - karena Pemeta benar-benar bergantung pada koneksi database untuk melakukan save () - tetapi jika pembuat peta lain telah dibuat sebelumnya - ia dapat melewati langkah ini dalam memperoleh dependensinya. Meski rapi, tapi juga agak berantakan bukan?
sumber
Ada alternatif lain selain Singleton: Proxy dan pola MonoState.
http://www.objectmentor.com/resources/articles/SingletonAndMonostate.pdf
Bagaimana pola proxy digunakan untuk menggantikan singleton?
sumber