Seringkali saya melihat implementasi pola builder (di Jawa) menjadi seperti ini:
public class Foo {
private Foo(FooBuilder builder) {
// get alle the parameters from the builder and apply them to this instance
}
public static class FooBuilder {
// ...
public Foo build() {
return new Foo(this); // <- this part is what irritates me
}
}
}
Contoh juga di sini:
- /programming/25130510/builder-pattern-in-java
- https://www.javacodegeeks.com/2013/01/the-builder-pattern-in-practice.html
Mengapa orang memperkenalkan ketergantungan (saling) kuat antara pembangun dan tipe untuk membangun?
EDIT: Maksud saya, saya tahu bahwa pada dasarnya pembangun terkait dengan kelas yang ingin saya bangun instance dari ( FooBuilder -> Foo
). Yang saya tanyakan adalah: mengapa ada kebutuhan untuk sebaliknya ( Foo -> FooBuilder
)
Sebaliknya saya melihat (lebih jarang) implementasi yang membuat instace baru Foo
ketika builder dibuat dan mengatur bidang pada instance Foo
ketika metode builder yang sesuai dipanggil. Saya suka pendekatan ini lebih baik, karena masih memiliki API yang lancar dan tidak mengikat kelas untuk pembangunnya. Apakah ada kelemahan dari pendekatan lain ini?
Foo
konstruktor bersifat publik?Jawaban:
Itu bermuara untuk tidak pernah memiliki Foo dalam keadaan setengah dibangun
Beberapa alasan yang muncul dalam pikiran:
Sang pembangun pada dasarnya terikat pada kelas yang dibangunnya. Anda dapat menganggap status perantara dari pembangun sebagai aplikasi sebagian konstruktor, sehingga argumen Anda bahwa itu terlalu berpasangan tidak persuasif.
Dengan melewati seluruh builder, bidang di MyClass bisa final, membuat penalaran tentang MyClass lebih mudah. Jika bidang tidak final, Anda bisa dengan mudah memiliki setter lancar dari pembangun.
sumber
Pembangun akan memegang bidang yang bisa berubah, diatur dengan metode. Kelas aktual (
Foo
) kemudian dapat membuatfinal
bidang tidak berubah dari pembangun.Jadi Builder adalah kelas stateful.
Tapi pembangun lain bisa saja menelepon
new Foo(x, y, z)
. Itu akan lebih satu arah, IMHO gaya yang lebih baik. Saat anti-pola, bidang FooBuilder atau semacamnya tidak akan mungkin. Di sisi lain, FooBuilder menjamin integritas data.Di sisi lain, FooBuilder memainkan dua peran: untuk membangun dengan API yang lancar, dan untuk menyajikan data ke konstruktor. Ini adalah kelas tipe acara untuk konstruktor. Dalam kode overdesigned params konstruktor dapat disimpan di beberapa FooConstructorParams.
sumber
Karena "Builder" biasanya digunakan untuk memecahkan "masalah konstruktor teleskop", terutama dalam konteks kelas yang tidak dapat diubah. Lihat tautan ini untuk contoh lengkap.
Pertimbangkan seperti apa alternatifnya:
Atau:
Jadi terutama untuk kelas yang tidak dapat diubah, jika Anda tidak menginginkan konstruktor dengan banyak parameter, sebenarnya tidak ada alternatif.
sumber
foo.Attribute1=par1
memungkinkan,Foo
pasti bisa berubah, bahkan di Jawa. Kelas yang tidak dapat berubah perlu untuk melarang mutasi negara mereka setelah konstruksi, baik dengan setter, atau dengan metode mutasi negara mereka, atau dengan mengekspos atribut anggota publik.