Saya mengembangkan API tenang dan saya pikir itu nyaman untuk menggunakan DAO untuk sumber daya saya karena walaupun saya berencana hanya menggunakan memori untuk menyimpannya, saya tidak ingin menutup pintu kepada siapa pun yang menggunakan perpustakaan saya jika mereka memutuskan untuk menggunakan implementasi basis data untuk DAO.
Pertanyaan saya adalah apakah DAO harus tunggal atau tidak. Jika tidak, layanan akan memiliki instance DAO dan akan terlihat seperti ini:
@Path("eventscheduler")
public class EventSchedulerService {
private IEventSchedulerDao dao = new EventSchedulerDao();
// in case a different implementation is to be used
public void setEventSchedulerDao(IEventSchedulerDao dao) {
this.dao = dao;
}
@Path("{uniqueName}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Tournament getTournament(@PathParam("name") String uniqueName) {
return dao.get(uniqueName);
}
@Path("create")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Tournament createTournament(Tournament tournament) {
return dao.create(tournament);
}
}
Sementara jika DAO adalah singleton, tapi saya kira tidak akan ada banyak perbedaan, hanya di baris pertama:
private IEventSchedulerDao dao = EventSchedulerDao.getInstance();
Saya masih harus menggunakan IEventSchedulerDao
contoh, tapi saya kira semua lajang bekerja seperti ini kan? Untuk beberapa alasan saya selalu menghubungkan singleton dengan metode statis, jadi alih-alih memiliki instance tunggal yang terlihat oleh pengguna getInstance()
, ini akan disembunyikan dan dia hanya akan menggunakan EventSchedulerDao.get(name)
, dll ... dengan cara statis. Apakah ini sesuatu atau ini hanya saya?
Jadi, haruskah saya atau saya tidak memiliki DAO tunggal?
Dan sebagai pertanyaan sampingan, apakah tidak apa-apa pendekatan saya untuk membuka pintu bagi pengguna untuk mengimplementasikan DAO mereka sendiri?
Jawaban:
Saya tidak akan menggunakan singleton. Ini adalah anti-pola yang dikenal , dan membuat pengujian menjadi sulit. Saya lebih suka menyuntikkan dalam implementasi konkret, dan meminta layanan Anda antarmuka DAO (memungkinkan Anda untuk menyuntikkan implementasi yang berbeda di)
sumber
private IEventSchedulerDao dao = new EventSchedulerDao();
adalah tempat Anda salah. Implementasi untukIEventSchedulerDao
harus disuntikkan melalui konstruktor dan tidak pernah berubah (yaitu, singkirkansetEventSchedulerDao
juga).A D ata A ccess O bject seharusnya hanya benar-benar ada satu kali dalam aplikasi Anda. Logikanya tetap sama, satu-satunya hal yang berbeda adalah nilai-nilai yang masuk dan keluar dari metode yang disediakan oleh DAO.
Dengan mengingat hal itu, jelas hal pertama yang biasanya terjadi adalah menerapkan DAO sebagai singleton yang kuat , yaitu ketika Anda memiliki
static
metode pada kelas pabrik, sesuatu sepertigetInstance
, malas memuat instance DAO jika itu nol dan mengembalikannya.Maaf jika sintaksnya tidak sepenuhnya benar, saya bukan programmer Java.
Ini sangat sulit untuk diuji, karena Anda tidak dapat menukar implementasi tanpa mengubah kode
UsesDao
kelas. Itu bisa dilakukan melalui beberapa patch monyet , tetapi umumnya tidak dianggap sebagai praktik yang baik.Lalu ada cara yang lebih baik, pola singleton yang lemah , di mana Anda tidak mengambil instance melalui
static
metode, tetapi membuat semua kelas bergantung pada instance baik melalui konstruktor atau setter (di AndaEventSchedulerService
Anda menggunakan injeksi setter).Satu-satunya masalah adalah, Anda kemudian perlu memastikan bahwa semua kelas, yang bergantung pada turunan kelas yang seharusnya hanya ada setelah siklus hidup aplikasi Anda, mengambil contoh yang sama dengan parameternya, yaitu. yang
new
disebut hanya sekali pada objek DAO di seluruh aplikasi.Jelas, ini sangat sulit untuk dilacak dan membangun objek-grafik adalah pekerjaan yang membosankan dan menjengkelkan.
Untungnya, ada wadah IOC , yang membuatnya jauh lebih mudah. Selain Spring , wadah Guice IoC oleh Google cukup populer di kalangan programmer Java.
Saat menggunakan wadah IoC, Anda mengkonfigurasinya untuk berperilaku dengan cara tertentu, yaitu. Anda memberi tahu jika bagaimana seharusnya membangun kelas-kelas tertentu dan jika beberapa kelas diperlukan sebagai dependensi, bagaimana dependensi seharusnya terlihat (apakah itu harus selalu menjadi contoh baru atau singleton) dan wadah itu menghubungkan semuanya.
Anda dapat memeriksa tautan ini untuk contoh tunggal dengan Guice.
Pro dan kontra menggunakan wadah IoC
Pro
Cons
sumber
Singleton merujuk pada konsep hanya satu instance dan cara untuk mendapatkan akses ke instance (melalui metode statis yang sangat terkenal, getInstance () )
Tapi masih ada contoh di balik semua itu. Objek yang dibangun dengan semacam akses terbatas.
Dalam kasus Anda, saya lebih suka menggunakan pendekatan DI (injeksi ketergantungan). Seperti blok kode pertama yang telah Anda tampilkan. Hanya sedikit perubahan. Suntikkan DAO melalui konstruktor. Untuk menghapus atau tidak setter terserah Anda. Jika Anda ingin melindungi Pengendali dari perubahan dalam runtime kemudian hapus. Jika Anda ingin menawarkan kemungkinan seperti itu, maka pertahankanlah.
Anda benar menggunakan Antarmuka dan menawarkan jendela terbuka untuk implementasi DAO lebih lanjut. Mungkin atau mungkin tidak dibutuhkan. Hanya butuh satu menit lebih banyak pekerjaan, tetapi ternyata desain Anda fleksibel. Anda DAO memori di adalah sangat umum. Sangat berguna sebagai tiruan pada saat pengujian. Atau sebagai implementasi DAO default.
Hanya sebuah petunjuk. Sumber daya statis (objek, metode, konstanta atau variabel) seperti sumber daya global. Jika global jahat atau tidak, itu masalah kebutuhan atau selera. Namun ada kelemahan implisit yang terikat pada mereka. Ini terkait dengan concurrency , thread-safety (di Jawa, tidak tahu tentang bahasa lain), serialisasi ...
Jadi saya menyarankan untuk menggunakan statika dengan hati-hati
sumber