Beberapa masalah dengan lajang enum:
Berkomitmen pada strategi implementasi
Biasanya, "singleton" mengacu pada strategi implementasi, bukan spesifikasi API. Sangat jarang untuk Foo1.getInstance()
secara terbuka menyatakan bahwa itu akan selalu mengembalikan contoh yang sama. Jika diperlukan, implementasi Foo1.getInstance()
dapat berkembang, misalnya, untuk mengembalikan satu instance per utas.
Dengan Foo2.INSTANCE
kita secara terbuka menyatakan bahwa hal ini adalah dengan contoh, dan tidak ada kesempatan untuk mengubah itu. Strategi implementasi memiliki satu contoh terbuka dan berkomitmen untuk.
Masalah ini tidak melumpuhkan. Misalnya, Foo2.INSTANCE.doo()
dapat mengandalkan objek pembantu lokal utas, untuk secara efektif memiliki instance per-utas.
Memperluas kelas Enum
Foo2
memperluas kelas super Enum<Foo2>
. Kami biasanya ingin menghindari kelas super; terutama dalam kasus ini, kelas super yang dipaksakan Foo2
tidak ada hubungannya dengan apa Foo2
yang seharusnya. Itu adalah polusi pada jenis hierarki aplikasi kita. Jika kita benar-benar menginginkan kelas super, biasanya kelas aplikasi, tetapi kita tidak bisa, Foo2
kelas supernya sudah diperbaiki.
Foo2
mewarisi beberapa metode contoh lucu seperti name(), cardinal(), compareTo(Foo2)
, yang hanya membingungkan Foo2
pengguna. Foo2
tidak dapat memiliki name()
metode sendiri bahkan jika metode itu diinginkan dalam Foo2
antarmuka.
Foo2
juga mengandung beberapa metode statis lucu
public static Foo2[] values() { ... }
public static Foo2 valueOf(String name) { ... }
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
yang tampaknya tidak masuk akal bagi pengguna. Singleton biasanya tidak seharusnya memiliki metode statis pulbic (selain dari getInstance()
)
Serializability
Sangat umum bagi lajang untuk menyatakan diri. Lajang ini umumnya tidak boleh serial. Saya tidak bisa memikirkan contoh realistis di mana masuk akal untuk mengangkut singleton stateful dari satu VM ke VM lain; singleton berarti "unik di dalam VM", bukan "unik di alam semesta".
Jika serialisasi benar-benar masuk akal untuk singleton stateful, singleton harus secara eksplisit dan tepat menentukan apa artinya deserialisasi singleton di VM lain di mana singleton dari tipe yang sama mungkin sudah ada.
Foo2
secara otomatis berkomitmen pada strategi serialisasi / deserialisasi sederhana. Itu hanya kecelakaan yang menunggu untuk terjadi. Jika kita memiliki pohon data yang secara konseptual merujuk variabel keadaan Foo2
dalam VM1 di t1, melalui serialisasi / deserialisasi nilai menjadi nilai yang berbeda - nilai variabel yang sama Foo2
di dalam VM2 di t2, membuat sulit untuk mendeteksi bug. Bug ini tidak akan terjadi pada yang tidak dapat digunakan Foo1
diam-diam.
Batasan pengkodean
Ada hal yang bisa dilakukan di kelas normal, tetapi dilarang di enum
kelas. Misalnya, mengakses bidang statis di konstruktor. Programmer harus lebih berhati-hati karena dia bekerja di kelas khusus.
Kesimpulan
Dengan membonceng enum, kami menyimpan 2 baris kode; tetapi harga terlalu tinggi, kita harus membawa semua kantong dan pembatasan enum, kita secara tidak sengaja mewarisi "fitur" enum yang memiliki konsekuensi yang tidak diinginkan. Satu-satunya keuntungan yang diduga - serializability otomatis - ternyata menjadi kerugian.