Apakah argumen bernama mengganti pola builder?

20

Saat menggunakan bahasa yang mendukung argumen bernama dan opsional, apakah pola pembangun tidak lagi memiliki penggunaan praktis?

Pembangun:

new Builder(requiredA, requiredB).setOptionalA("optional").Build();

Argumen opsional / bernama:

new Object(requiredA, requiredB, optionalA: "optional");
Paul Nikonowicz
sumber
3
Bagaimana Anda menangani 20 argumen opsional? Tidak ada masalah yang harus diselesaikan Builder sampai menjadi besar. Pada titik yang Anda jelaskan di sini, Anda memiliki dua konstruktor (dan saya tidak akan membangun Builder untuk masalah kecil itu).
1
Bahkan dengan argumen opsional - jika konstruktor memiliki lebih dari 2 argumen, saya lebih suka menggunakan objek nilai untuk merangkum konfigurasi. Hal yang sama berlaku untuk inerfaces dan pembangun fluida: Apa pun yang lebih besar dari 3 akan diganti oleh objek nilai.
Thomas Junk

Jawaban:

21

Pembangun paling berguna ketika objek Anda membutuhkan banyak argumen / dependensi untuk menjadi berguna, atau Anda ingin mengizinkan berbagai cara membangun objek.

Dari atas kepala saya, saya bisa membayangkan seseorang mungkin ingin "membangun" objek dalam game 3D seperti ini:

// Just ignore the fact that this hypothetical god class is coupled to everything ever
new ObjectBuilder(x, y, z).importBlenderMesh("./meshes/foo")
                          .syncWithOtherPlayers(serverIP)
                          .compileShaders("./shaders/foo.vert", "./shaders/foo.frag")
                          .makeDestructibleRigidBody(health, weight)
                          ...

Saya berpendapat contoh ini lebih mudah dibaca dengan metode builder yang saya buat sekarang dibandingkan dengan parameter opsional:

new Object(x, y, z, meshType: MESH.BLENDER,
                    meshPath: "./meshes/foo",
                    serverToSyncWith: serverIP,
                    vertexShader: "./shaders/foo.vert",
                    physicsType: PHYSICS_ENGINE.RIGID_DESTRUCTIBLE,
                    health: health,
                    weight: weight)
                    ...

Secara khusus, informasi yang tersirat oleh nama metode pembangun harus diganti dengan lebih banyak parameter, dan jauh lebih mudah untuk melupakan satu parameter dalam kelompok parameter yang terkait erat. Sebenarnya, shader fragmen hilang, tetapi Anda tidak akan menyadarinya kecuali Anda tahu untuk mencarinya.


Tentu saja, jika objek Anda hanya membutuhkan satu hingga lima argumen untuk dikonstruksikan, tidak perlu melibatkan pola pembangun, terlepas apakah Anda telah menamai atau parameter opsional.

Ixrec
sumber
Saya tidak membeli argumen Anda. Jika nama metode pembuat sangat bagus, Anda dapat menggunakannya juga untuk nama parameter. Jika parameter terkait erat, masukkan mereka ke dalam konstruktor objek kecil.
user949300
@ user949300 Saya pikir Anda telah melewatkan bagian penting dari titik, yaitu bahwa metode pembangun di sini menggambarkan hubungan antara parameter yang hilang jika Anda hanya memiliki banyak parameter opsional. Dalam contoh pembangun Ixrec, "kesehatan" dan "berat" jelas merupakan bagian dari pengaturan tubuh yang dapat dirusak secara logis, tetapi hubungan itu l hilang dalam versi argumen opsional.
Jules
1
tidak jika salah satu parameter opsional adalah (tubuh: new DestructibleRigidBody (kesehatan, berat), ...)
Weyland Yutani
@ Jules. Apa yang dikatakan Weyland - buat konstruktor kecil yang terkenal untuk berat & tinggi badan.
user949300
8

Selain apa yang dikatakan Ixrec, konstruktor atau metode bernama parameter tidak akan memungkinkan Anda untuk memiliki objek Anda dalam kondisi yang akan dibangun di mana ia masih dapat dimodifikasi sebelum membangunnya. Ini adalah keindahan dari Builder, di mana Anda dapat mendelegasikan bagian dari konstruksinya ke metode atau kelas yang berbeda:

var myThingBuilder = new ThingBuilder("table");
myThingBuilder.setAttribute(Attributes.Legs, 4);

inventoryManager.setPrices(myThingBuilder);

// inventory manager
var availableCheapestMaterial = getMaterial();
myThingBuilder.setMaterial(availableCheapestMaterial);

Pada dasarnya, Anda juga dapat melemparkan pembangun Anda di sekitar sistem Anda sampai siap untuk membangun objek akhir, memungkinkan Anda untuk mengurangi jumlah pengetahuan yang perlu dimiliki oleh pembangun-konsumen Anda.

Alfa
sumber
Saya tidak mengerti paragraf terakhir Anda. Jika Anda "melempar pembangun di sekitar sistem hingga siap", ia memiliki terlalu banyak pengetahuan tentang sistem. ThingBuilder Anda tahu tentang Atribut, secara misterius dimodifikasi oleh InventoryManager, dan tahu tentang Materi. Tidak melihat bagaimana hal itu mengurangi pengetahuan.
user949300
@ user949300 Pikirkan bagaimana jadinya tanpa pembangun yang bepergian melintasi sistem. Anda akan dipaksa untuk memiliki kelas dengan faktor penggemarnya yang besar, dan itu hanya perlu untuk membangun Benda. (Tentu saja, dengan asumsi kelas Anda tidak memusatkan semua pengetahuan, inilah yang ingin kami hindari sejak awal.) Sekarang, jika kelas ini memiliki tanggung jawab lain, Anda menciptakan kelas besar, memecahkan S dalam SOLID . Jika itu satu-satunya tanggung jawab, Anda menjadikan diri Anda seorang ThingBuilder.
Alpha
1

Itu tergantung pada apa yang Anda lakukan dengan pembangun.

Jika Anda menggunakan builder hanya untuk mengatur (dan memvariasikan) properti objek dan (menunda) pembuatan objek, itu bisa diganti dengan param bernama.

Mengganti pembangun Anda mungkin memiliki tradeoff keterbacaan / penggunaan yang @decrec mentoned (atau mungkin tidak memilikinya, itu tergantung pada apa yang Anda lakukan dengan pembangun).

Namun, jika pembuat Anda tidak hanya memegang properti dan setiap langkah konstruksi melibatkan logika, itu tidak dapat diganti.

MockBuilder adalah contoh di mana ia tidak bisa diganti dengan param bernama. Dari halaman:

Logika tentang langkah-langkah pembuatan tidak dapat diganti dengan param bernama

rvazquezglez
sumber
-5

Pola pembangun sangat penting ketika bekerja dengan benda yang tidak dapat diubah. Ada banyak manfaat bekerja dengan objek yang tidak dapat diubah, terutama dalam membuat program Anda menjadi lebih kuat dieksekusi di lingkungan bersamaan (yaitu, utas)

codedabbler
sumber
3
Ya, Builder sangat bagus untuk bekerja dengan objek yang tidak dapat diubah yang kompleks (atau bahkan yang bisa berubah - Anda perlu memastikan bahwa objek tersebut dalam keadaan konsisten sebelum dapat digunakan). Yang mengatakan, new Integer(42), new BigDecimal("42.000")dan new String("foobar")semua konstruktor untuk immutables yang ... baik, pembangun akan sia-sia kompleks untuk hal ini. Jadi pembangun tidak penting untuk bekerja dengan kekal ketika konstruktor dapat bekerja dengan baik.
Ya, konstruktor dapat digunakan dengan objek yang tidak dapat diubah, yang tidak ditolak. Tetapi pertanyaan awal adalah apakah pola Builder memiliki penggunaan praktis selain dari argumen opsional dan tanggapan saya adalah untuk memperjelas ini.
codedabbler
2
Pertanyaan aslinya tidak mengatakan apa - apa tentang benda yang tidak bisa diubah. Ia bertanya tentang parameter bernama dan hubungannya dengan Builder. Jawaban Anda adalah tentang pembangun dan hubungannya dengan objek yang tidak dapat diubah. Saya kesulitan melihat bagaimana jawaban Anda menjawab pertanyaan itu.