Mengapa menggunakan metode tunggal dan bukan statis?

94

Saya tidak pernah menemukan jawaban yang bagus untuk pertanyaan sederhana tentang kelas helper / utility ini:

Mengapa saya membuat singleton (stateless) daripada menggunakan metode statis?

Mengapa sebuah instance objek diperlukan jika sebuah objek tidak memiliki status?

Sebastien Lorber
sumber
kemungkinan duplikat stackoverflow.com/questions/720744/static-class-and-singleton
Michael Borgwardt
Jangan berpikir karena kita berbicara tentang 2 bahasa yang berbeda jadi jawabannya mungkin berbeda, tapi terima kasih untuk linknya, di java tidak pernah mendengar istilah "monostate"
Sebastien Lorber

Jawaban:

79

Seringkali, lajang digunakan untuk memperkenalkan beberapa jenis status global ke suatu aplikasi. (Lebih sering daripada yang sebenarnya diperlukan, jujur ​​saja, tapi itu topik untuk lain waktu.)

Namun, ada beberapa kasus sudut di mana bahkan singleton tanpa kewarganegaraan pun dapat berguna:

  • Anda berharap untuk memperpanjangnya dengan negara bagian di masa mendatang.
  • Anda memerlukan contoh objek untuk beberapa alasan teknis tertentu .
    Contoh: Objek sinkronisasi untuk C # lockatau synchronizedpernyataan Java .
  • Anda membutuhkan warisan, yaitu, Anda ingin dapat dengan mudah mengganti singleton Anda dengan yang lain menggunakan antarmuka yang sama tetapi implementasi yang berbeda.
    Contoh: Toolkit.getDefaultToolkit()Metode di Java akan mengembalikan singleton yang tipe pastinya bergantung pada sistem.
  • Anda menginginkan persamaan referensi untuk nilai sentinel .
    Contoh: DBNull.Valuedi C #.
Heinzi
sumber
27
Saya akan memilih +1, meskipun lajang IMHO disalahgunakan untuk memperkenalkan negara global. Tujuan singleton bukanlah untuk membuat objek tersedia secara global, tetapi untuk memastikan bahwa sebuah objek hanya dibuat satu kali. Objek global adalah kejahatan yang diperlukan. Kecuali benar-benar diperlukan, seseorang harus mencoba untuk tidak menggunakannya, karena mereka umumnya mengarah ke penggandengan yang tinggi, dengan SomeSingleton.getInstance (). SomeMethod () di semua tempat. :)
back2dos
Ini dapat berguna dalam game di mana Anda hanya menginginkan satu instance render daripada beberapa instance render, atau dengan kelas perpipaan jaringan tempat Anda menyiapkan saluran aman yang hanya dapat memiliki satu koneksi dalam satu waktu.
Tschallacka
2
Bagian "gantilah singleton dengan mudah" adalah poin terpenting menurut saya. Istirahat cukup dekat dengan implementasi kelas statis.
Teoman shipahi
1
Singletons adalah nilai sentinel non-Null yang berguna untuk jumlah / jenis produk dan sejenisnya. Misalnya, menjadi nilai Tidak Ada / Tidak Ada dalam tipe Opsi atau nilai Kosong untuk tipe koleksi. Anda mendapatkan pengujian Tidak Ada / Kosong yang cepat sebagai bonus, karena hanya persamaan referensi yang dibutuhkan.
itsbruce
@itsbruce: Contoh Anda bukan lajang : Daftar kosong bukan satu-satunya contoh yang mungkin dari kelas Daftar, dan nilai Tidak Ada bukan satu-satunya contoh yang mungkin dari kelas Opsi. Namun, ada contoh di mana nilai sentinel adalah lajang, dan saya dengan bebas menambahkan satu ke jawaban saya. Terima kasih atas masukannya!
Heinzi
37

Saya bisa melihat kasus untuk singleton tanpa kewarganegaraan yang digunakan sebagai pengganti kelas metode statis, yaitu untuk Injeksi Ketergantungan .

Jika Anda memiliki kelas pembantu dari fungsi utilitas yang Anda gunakan secara langsung, ini akan membuat ketergantungan tersembunyi; Anda tidak memiliki kendali atas siapa yang dapat menggunakannya, atau di mana. Memasukkan kelas helper yang sama melalui instans tunggal tanpa negara memungkinkan Anda mengontrol di mana dan bagaimana kelas itu digunakan, dan menggantinya / mengejeknya / dll. Bila perlu.

Menjadikannya instance tunggal hanya memastikan bahwa Anda tidak mengalokasikan objek jenis lebih dari yang diperlukan (karena Anda hanya membutuhkan satu objek).

tzaman
sumber
1
"Anda tidak memiliki kendali atas siapa yang dapat menggunakannya, atau di mana." Mengapa seseorang membutuhkannya?
hagrawal
1
@hagrawal untuk tujuan pengujian, Anda harus dapat mengejeknya
Jemshit Iskenderov
15

Sebenarnya saya telah menemukan jawaban lain yang tidak disebutkan di sini: metode statis lebih sulit untuk diuji.

Tampaknya sebagian besar framework pengujian berfungsi dengan baik untuk mengejek metode instance, tetapi banyak di antaranya tidak menangani metode statis tiruan dengan cara yang layak.

Sebastien Lorber
sumber
2
Tapi Powermock tampaknya mampu melakukannya
Sebastien Lorber
6

Dalam kebanyakan bahasa pemrograman, kelas menghindari banyak tipe sistem. Meskipun kelas, dengan metode dan variabel statisnya adalah objek, sering kali ia tidak dapat mengimplementasikan antarmuka atau memperluas kelas lain. Oleh karena itu, ini tidak dapat digunakan secara polimorfik, karena tidak dapat menjadi subtipe dari tipe lain. Misalnya, jika Anda memiliki antarmuka IFooable, yang diperlukan oleh beberapa metode tanda tangan dari kelas-kelas lain, objek kelas StaticFootidak dapat digunakan di tempat IFooable, sedangkan FooSingleton.getInstance()kaleng (dengan asumsi, FooSingletonalat IFooable).

Harap dicatat, bahwa, saat saya mengomentari jawaban Heinzi, singleton adalah pola untuk mengontrol instansiasi. Ini menggantikan new Class()dengan Class.getInstance(), yang memberi penulisClass kontrol lebih besar atas instance, yang dapat dia gunakan untuk mencegah pembuatan instance yang tidak perlu. Singleton hanyalah kasus yang sangat khusus dari pola pabrik dan harus diperlakukan seperti itu. Penggunaan umum membuatnya menjadi kasus khusus dari pendaftar global, yang seringkali berakhir buruk, karena pendaftar global tidak boleh digunakan sembarangan.

Jika Anda berencana untuk menyediakan fungsi helper global, metode statis akan berfungsi dengan baik. Kelas tidak akan bertindak sebagai kelas, melainkan hanya sebagai namespace. Saya sarankan, Anda mempertahankan kohesi tinggi, atau Anda mungkin berakhir dengan masalah kopling yang paling aneh.

greetz
back2dos

back2dos
sumber
4

Ada trade-off antara menggunakan yang mana. Lajang mungkin atau mungkin tidak memiliki status dan mereka mengacu pada objek. Jika mereka tidak menyimpan status dan hanya digunakan untuk akses global, maka statis lebih baik karena metode ini akan lebih cepat. Tetapi jika Anda ingin menggunakan objek dan konsep OOP (Inheritance polymorphism), maka singleton lebih baik.

Perhatikan contoh: java.lang.Runtime adalah kelas tunggal di java. Kelas ini memungkinkan implementasi yang berbeda untuk setiap JVM. Implementasinya tunggal per JVM. Jika kelas ini statis, kami tidak dapat meneruskan implementasi yang berbeda berdasarkan JVM.

Saya menemukan tautan ini sangat membantu: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?

Semoga membantu !!

Atihska
sumber
Jawaban ini bagus untuk memasukkan contoh konkret di dunia nyata.
systemovich
2

Bagi saya "Ingin Status Objek menggunakan Singleton, Ingin Fungsi menggunakan metode statis"

Itu tergantung pada apa yang Anda inginkan. Kapan pun Anda menginginkan status objek (misalnya, Polimorfisme seperti status Null null, atau status default), singleton adalah pilihan yang tepat untuk Anda sedangkan metode statis digunakan saat Anda membutuhkan fungsi (Terima input lalu kembalikan output).

Saya merekomendasikan untuk kasus tunggal, itu harus selalu dalam keadaan yang sama setelah dipakai. Seharusnya tidak dapat di-clonable, atau menerima nilai apa pun untuk disetel (kecuali konfigurasi statis dari file misalnya file properti di java).

PS Kinerja antara 2 ini berbeda dalam milidetik, jadi fokuslah pada Arsitektur terlebih dahulu.

Toomtarm Kung
sumber
1

Singleton bukan tanpa kewarganegaraan, ia memegang status global.

Beberapa alasan yang dapat saya pikirkan untuk menggunakan Singleton adalah:

  • Untuk menghindari kebocoran memori
  • Untuk memberikan status yang sama untuk semua modul dalam aplikasi, misalnya koneksi database
Indigo Praveen
sumber
Aku tahu tapi sebenarnya seorang lajang bisa lebih atau kurang tanpa kewarganegaraan ... Jika tidak berbagi atribut kelas apapun ...
Sebastien Lorber