Di Java dan C #, Anda bisa membuat objek dengan properti yang dapat diatur pada inisialisasi dengan mendefinisikan konstruktor dengan parameter, menentukan setiap properti setelah membangun objek, atau menggunakan pola antarmuka pembangun / fluida. Namun, C # 3 memperkenalkan inisialisasi objek dan koleksi, yang berarti pola pembangun sebagian besar tidak berguna. Dalam bahasa tanpa inisialisasi, seseorang dapat mengimplementasikan builder lalu menggunakannya seperti:
Vehicle v = new Vehicle.Builder()
.manufacturer("Toyota")
.model("Camry")
.year(1997)
.colour(CarColours.Red)
.addSpecialFeature(new Feature.CDPlayer())
.addSpecialFeature(new Feature.SeatWarmer(4))
.build();
Sebaliknya, dalam C # seseorang dapat menulis:
var vehicle = new Vehicle {
Manufacturer = "Toyota",
Model = "Camry",
Year = 1997,
Colour = CarColours.Red,
SpecialFeatures = new List<SpecialFeature> {
new Feature.CDPlayer(),
new Feature.SeatWarmer { Seats = 4 }
}
}
... menghilangkan kebutuhan akan pembangun seperti yang terlihat pada contoh sebelumnya.
Berdasarkan contoh-contoh ini, apakah pembangun masih berguna dalam C #, atau mereka telah digantikan seluruhnya oleh inisialisasi?
c#
object-oriented
builder-pattern
svbnet
sumber
sumber
are builders useful
mengapa saya terus melihat pertanyaan-pertanyaan semacam ini? Builder adalah pola desain - tentu saja, itu dapat diekspos sebagai fitur bahasa tetapi pada akhirnya itu hanya pola desain. Pola desain tidak boleh "salah". Itu mungkin atau mungkin tidak memenuhi kasus penggunaan Anda tetapi itu tidak membuat seluruh pola salah, hanya penerapannya. Ingatlah bahwa pada akhirnya pola desain memecahkan masalah tertentu - jika Anda tidak menghadapi masalah, lalu mengapa Anda mencoba menyelesaikannya?Jawaban:
Seperti yang disentuh oleh @ user248215 masalah sebenarnya adalah ketidakberdayaan. Alasan Anda akan menggunakan pembangun di C # adalah untuk mempertahankan kejujuran penginisialisasi tanpa harus mengekspos properti yang bisa diatur. Ini bukan pertanyaan tentang enkapsulasi, itulah sebabnya saya telah menulis jawaban saya sendiri. Enkapsulasi cukup ortogonal karena memohon setter tidak menyiratkan apa yang sebenarnya dilakukan setter atau mengikat Anda pada implementasinya.
Versi selanjutnya dari C #, 8.0, kemungkinan akan memperkenalkan
with
kata kunci yang akan memungkinkan objek yang tidak dapat diubah diinisialisasi dengan jelas dan singkat tanpa perlu menulis pembangun.Hal menarik lain yang dapat Anda lakukan dengan pembangun, bukan inisialisasi, adalah bahwa mereka dapat menghasilkan berbagai jenis objek tergantung pada urutan metode yang disebut.
Sebagai contoh
Hanya untuk memperjelas contoh di atas, itu adalah pustaka pencocokan pola yang menggunakan pola pembangun untuk membangun "kecocokan" dengan menentukan kasus. Kasing ditambahkan dengan memanggil
Case
metode yang melewatinya fungsi. Jikavalue
ditugaskan untuk tipe parameter fungsi itu dipanggil. Anda dapat menemukan kode sumber lengkap di GitHub dan, karena komentar XML sulit dibaca dalam teks biasa, berikut ini tautan ke dokumentasi yang dibuat oleh SandCastle (lihat bagian Keterangan )sumber
IEnumerable<Func<T, TResult>>
anggota.TResult
. Pada akhirnya tipe-inferensi banyak berhubungan dengan itu. Saya juga ingin "terlihat" seperti struktur kontrol. Juga saya tidak ingin menggunakan penginisialisasi karena itu akan memungkinkan mutasi.Penginisialisasi objek mensyaratkan bahwa properti harus dapat diakses oleh kode panggilan. Pembangun bersarang dapat mengakses anggota pribadi kelas.
Jika Anda ingin menjadikan
Vehicle
tidak berubah (melalui membuat semua setter pribadi), maka pembuat bersarang dapat digunakan untuk mengatur variabel pribadi.sumber
Mereka semua melayani keperluan yang berbeda !!!
Konstruktor dapat menginisialisasi bidang yang ditandai
readonly
serta anggota pribadi dan yang dilindungi. Namun, Anda agak terbatas pada apa yang dapat Anda lakukan di dalam konstruktor; Anda harus menghindari meneruskanthis
ke metode eksternal, misalnya, dan Anda harus menghindari memanggil anggota virtual, karena mereka dapat mengeksekusi dalam konteks kelas turunan yang belum dibangun sendiri. Selain itu, konstruktor dijamin untuk dijalankan (kecuali jika pemanggil melakukan sesuatu yang sangat tidak biasa), jadi jika Anda mengatur bidang dalam konstruktor, kode di seluruh kelas dapat mengasumsikan bahwa bidang tersebut tidak akan menjadi nol.Inisialisasi dijalankan setelah konstruksi. Mereka hanya membiarkan Anda memanggil properti publik; bidang pribadi dan / atau hanya baca tidak dapat disetel. Dengan konvensi, tindakan menetapkan properti harus sangat terbatas, misalnya harus idempoten, dan memiliki efek samping yang terbatas.
Metode pembangun adalah metode aktual dan karenanya memungkinkan lebih dari satu argumen, dan dengan konvensi dapat memiliki efek samping termasuk pembuatan objek. Meskipun mereka tidak dapat mengatur bidang baca saja, mereka dapat melakukan hal lain. Juga, metode dapat diimplementasikan sebagai metode ekstensi (seperti hampir semua fungsi LINQ).
sumber