Mengapa saya harus menggunakan kelas pabrik alih-alih konstruksi objek langsung?

162

Saya telah melihat sejarah beberapa proyek pustaka kelas С dan Java pada GitHub dan CodePlex, dan saya melihat tren beralih ke kelas pabrik sebagai lawan instantiasi objek langsung.

Mengapa saya harus menggunakan kelas pabrik secara ekstensif? Saya memiliki perpustakaan yang cukup bagus, di mana objek dibuat dengan cara kuno - dengan memanggil konstruktor publik kelas. Dalam komit terakhir, penulis dengan cepat mengubah semua konstruktor publik dari ribuan kelas menjadi internal, dan juga menciptakan satu kelas pabrik besar dengan ribuan CreateXXXmetode statis yang baru saja mengembalikan objek baru dengan memanggil konstruktor internal kelas. API proyek eksternal rusak, dilakukan dengan baik.

Mengapa perubahan seperti itu bermanfaat? Apa gunanya refactoring dengan cara ini? Apa manfaat mengganti panggilan ke konstruktor kelas publik dengan panggilan metode pabrik statis?

Kapan saya harus menggunakan konstruktor publik, dan kapan saya harus menggunakan pabrik?

rufanov
sumber

Jawaban:

56

Kelas pabrik sering diterapkan karena memungkinkan proyek untuk mengikuti prinsip-prinsip SOLID lebih dekat. Secara khusus, prinsip pemisahan segregasi dan dependensi.

Pabrik dan antarmuka memungkinkan fleksibilitas jangka panjang yang jauh lebih banyak. Ini memungkinkan desain yang lebih terpisah - dan karenanya lebih dapat diuji -. Berikut adalah daftar yang tidak lengkap tentang mengapa Anda mungkin menempuh jalan ini:

  • Ini memungkinkan Anda untuk memperkenalkan wadah Inversion of Control (IoC) dengan mudah
  • Itu membuat kode Anda lebih dapat diuji karena Anda dapat mengejek antarmuka
  • Ini memberi Anda lebih banyak fleksibilitas ketika tiba saatnya untuk mengubah aplikasi (yaitu Anda dapat membuat implementasi baru tanpa mengubah kode dependen)

Pertimbangkan situasi ini.

Majelis A (-> berarti tergantung pada):

Class A -> Class B
Class A -> Class C
Class B -> Class D

Saya ingin memindahkan Kelas B ke Majelis B, yang bergantung pada Majelis A. Dengan dependensi konkret ini saya harus memindahkan sebagian besar seluruh hierarki kelas saya. Jika saya menggunakan antarmuka, saya bisa menghindari banyak rasa sakit.

Majelis A:

Class A -> Interface IB
Class A -> Interface IC
Class B -> Interface IB
Class C -> Interface IC
Class B -> Interface ID
Class D -> Interface ID

Sekarang saya bisa memindahkan kelas B ke perakitan B tanpa rasa sakit sama sekali. Itu masih tergantung pada antarmuka dalam perakitan A.

Menggunakan wadah IoC untuk menyelesaikan ketergantungan Anda memungkinkan Anda lebih fleksibel. Tidak perlu memperbarui setiap panggilan ke konstruktor setiap kali Anda mengubah dependensi kelas.

Mengikuti prinsip pemisahan antarmuka dan prinsip inversi dependensi memungkinkan kita untuk membangun aplikasi yang sangat fleksibel dan dipisahkan. Setelah Anda mengerjakan salah satu dari jenis aplikasi ini, Anda tidak akan pernah lagi ingin kembali menggunakan newkata kunci.

Stephen
sumber
40
Pabrik IMO adalah hal yang paling tidak penting bagi SOLID. Anda dapat melakukan SOLID dengan baik tanpa pabrik.
Euforia
26
Satu hal yang tidak pernah masuk akal bagi saya adalah, jika Anda menggunakan pabrik untuk membuat objek baru maka Anda harus membuat pabrik di tempat pertama. Jadi apa sebenarnya yang membuat Anda? Apakah diasumsikan bahwa orang lain akan memberi Anda pabrik alih-alih Anda instantiasi sendiri, atau yang lain? Ini harus disebutkan dalam jawaban, jika tidak jelas bagaimana pabrik benar-benar menyelesaikan masalah.
Mehrdad
8
@ BЈовић - Kecuali setiap kali Anda menambahkan implementasi baru, Anda sekarang dapat membuka pabrik dan memodifikasinya untuk menjelaskan implementasi baru - secara eksplisit melanggar OCP.
Telastyn
6
@ Telastyn Ya, tetapi kode menggunakan objek yang dibuat tidak berubah. Itu lebih penting daripada perubahan ke pabrik.
BЈовић
8
Pabrik berguna di area tertentu yang jawabannya dijawab. Mereka tidak layak digunakan di mana-mana . Misalnya, menggunakan pabrik untuk membuat string atau daftar akan terlalu jauh. Bahkan untuk UDT mereka tidak selalu perlu. Kuncinya adalah menggunakan pabrik ketika implementasi antarmuka yang tepat harus dipisahkan.
126

Seperti kata whatsisname , saya percaya ini adalah kasus desain perangkat lunak pemujaan kargo . Pabrik, terutama jenis abstrak, hanya dapat digunakan ketika modul Anda membuat beberapa instance kelas dan Anda ingin memberi pengguna kemampuan modul ini untuk menentukan jenis yang akan dibuat. Persyaratan ini sebenarnya sangat jarang, karena sebagian besar waktu Anda hanya memerlukan satu instance dan Anda dapat langsung melewati instance itu alih-alih membuat pabrik yang eksplisit.

Masalahnya adalah, pabrik (dan lajang) sangat mudah diimplementasikan dan oleh karena itu banyak orang menggunakannya, bahkan di tempat-tempat di mana mereka tidak perlu. Jadi ketika programmer berpikir "Pola desain apa yang harus saya gunakan dalam kode ini?" Pabrik adalah yang pertama muncul di benaknya.

Banyak pabrik diciptakan karena "Mungkin, suatu hari, saya perlu membuat kelas-kelas itu secara berbeda" dalam pikiran. Yang jelas merupakan pelanggaran terhadap YAGNI .

Dan pabrik menjadi usang ketika Anda memperkenalkan kerangka kerja IoC, karena IoC hanyalah semacam pabrik. Dan banyak kerangka kerja IoC mampu menciptakan implementasi pabrik tertentu.

Juga, tidak ada pola desain yang mengatakan untuk membuat kelas statis besar dengan CreateXXXmetode yang hanya memanggil konstruktor. Dan itu terutama tidak disebut Pabrik (atau Pabrik Abstrak).

Euforia
sumber
6
Saya setuju dengan sebagian besar poin Anda kecuali "IoC adalah jenis pabrik" : Kontainer IoC bukan pabrik . Mereka adalah metode yang mudah untuk mencapai injeksi ketergantungan. Ya, beberapa mampu membangun pabrik otomatis, tetapi mereka bukan pabrik itu sendiri dan tidak boleh diperlakukan seperti itu. Saya juga akan menentang poin YAGNI. Berguna untuk mengganti tes ganda dalam tes unit Anda. Refactoring semuanya untuk memberikan ini setelah faktanya adalah rasa sakit di pantat . Rencanakan ke depan dan jangan jatuh untuk alasan "YAGNI"
AlexFoxGill
11
@AlexG - eh ... dalam praktiknya, hampir semua wadah IOC bekerja sebagai pabrik.
Telastyn
8
@AlexG Fokus utama IoC adalah untuk membangun objek konkret untuk diteruskan ke objek lain berdasarkan konfigurasi / konvensi. Ini sama dengan menggunakan pabrik. Dan Anda tidak perlu pabrik untuk dapat membuat tiruan untuk ujian. Anda hanya instantiate dan lulus mock langsung. Seperti yang saya katakan di paragraf pertama. Pabrik hanya berguna ketika Anda ingin meneruskan pembuatan instance ke pengguna modul, yang memanggil pabrik.
Euforia
5
Ada perbedaan yang harus dibuat. The pola pabrik digunakan oleh konsumen untuk membuat badan selama runtime dari sebuah program. Sebuah wadah IOC digunakan untuk membuat objek grafik dari program selama start-up. Anda dapat melakukan ini dengan tangan, wadah itu hanya kenyamanan. Konsumen sebuah pabrik tidak harus menyadari wadah IoC.
AlexFoxGill
5
Re: "Dan Anda tidak perlu pabrik untuk dapat membuat tiruan untuk diuji. Anda hanya instantiate dan lulus tiruan langsung" - lagi, keadaan yang berbeda. Anda menggunakan pabrik untuk meminta contoh - konsumen mengendalikan interaksi ini. Menyediakan contoh melalui konstruktor atau metode tidak berfungsi, ini skenario yang berbeda.
AlexFoxGill
79

Mode pola pabrik berasal dari keyakinan yang hampir dogmatis di antara coders dalam bahasa "C-style" (C / C ++, C #, Java) yang menggunakan kata kunci "baru" itu buruk, dan harus dihindari dengan segala cara (atau paling tidak tersentralisasi). Ini, pada gilirannya, berasal dari interpretasi yang sangat ketat dari Prinsip Tanggung Jawab Tunggal ("S" SOLID), dan juga dari Prinsip Inversi Ketergantungan ("D"). Secara sederhana, SRP mengatakan bahwa idealnya objek kode harus memiliki satu "alasan untuk berubah", dan hanya satu; bahwa "alasan untuk berubah" adalah tujuan utama dari objek itu, "tanggung jawabnya" dalam basis kode, dan hal lain apa pun yang memerlukan perubahan kode tidak boleh mengharuskan membuka file kelas itu. DIP bahkan lebih sederhana; objek kode tidak boleh bergantung pada objek konkret lain,

Contoh kasus, dengan menggunakan "baru" dan konstruktor publik, Anda menggabungkan kode panggilan ke metode konstruksi spesifik dari kelas beton tertentu. Kode Anda sekarang harus tahu bahwa kelas MyFooObject ada, dan memiliki konstruktor yang mengambil string dan int. Jika konstruktor itu membutuhkan lebih banyak informasi, semua penggunaan konstruktor harus diperbarui untuk memasukkan informasi itu termasuk yang sedang Anda tulis sekarang, dan oleh karena itu mereka diharuskan memiliki sesuatu yang valid untuk diteruskan, sehingga mereka harus memiliki atau diubah untuk mendapatkannya (menambahkan lebih banyak tanggung jawab ke objek yang mengkonsumsi). Selain itu, jika MyFooObject pernah diganti dalam basis kode oleh BetterFooObject, semua penggunaan kelas lama harus berubah untuk membangun objek baru, bukan yang lama.

Jadi, sebagai gantinya, semua konsumen MyFooObject harus langsung bergantung pada "IFooObject", yang mendefinisikan perilaku menerapkan kelas termasuk MyFooObject. Sekarang, konsumen IFooObjects tidak bisa hanya membangun IFooObject (tanpa memiliki pengetahuan bahwa kelas beton tertentu adalah IFooObject, yang tidak mereka butuhkan), jadi mereka harus diberi contoh kelas atau metode yang mengimplementasikan IFooObject dari luar, oleh objek lain yang memiliki tanggung jawab untuk mengetahui cara membuat objek IFooOb yang benar untuk keadaan tersebut, yang dalam bahasa kita biasanya dikenal sebagai Pabrik.

Sekarang, di sinilah teori bertemu kenyataan; suatu objek tidak pernah bisa ditutup untuk semua jenis perubahan sepanjang waktu. Contoh kasus, IFooObject sekarang menjadi objek kode tambahan dalam basis kode, yang harus berubah setiap kali antarmuka yang dibutuhkan oleh konsumen atau implementasi perubahan IFooObjects. Itu memperkenalkan tingkat kompleksitas baru yang terlibat dalam mengubah cara objek berinteraksi satu sama lain dalam abstraksi ini. Selain itu, konsumen masih harus berubah, dan lebih dalam lagi, jika antarmuka itu sendiri digantikan oleh yang baru.

Seorang programmer yang baik tahu bagaimana menyeimbangkan YAGNI ("Kamu Tidak Akan Membutuhkannya") dengan SOLID, dengan menganalisis desain dan menemukan tempat-tempat yang sangat mungkin harus berubah dengan cara tertentu, dan refactoring mereka agar lebih toleran terhadap bahwa jenis perubahan, karena dalam kasus "Anda adalah akan membutuhkannya".

KeithS
sumber
21
Cintai jawaban ini, khususnya setelah membaca semua yang lain. Saya dapat menambahkan hampir semua coders baru (baik) terlalu dogmatis tentang prinsip oleh fakta sederhana mereka benar-benar ingin menjadi baik tetapi belum belajar nilai dari menjaga hal-hal sederhana dan tidak berlebihan.
jean
1
Masalah lain dengan konstruktor publik adalah bahwa tidak ada cara yang baik bagi kelas Foountuk menentukan konstruktor publik harus dapat digunakan untuk pembuatan Fooinstance, atau pembuatan tipe lain dalam paket / perakitan yang sama , tetapi tidak boleh digunakan untuk pembuatan jenis yang diturunkan di tempat lain. Saya tidak tahu alasan khusus yang memaksa suatu bahasa / kerangka kerja tidak dapat mendefinisikan konstruktor terpisah untuk digunakan dalam newekspresi, dibandingkan permintaan dari konstruktor subtipe, tapi saya tidak tahu bahasa apa pun yang membuat perbedaan itu.
supercat
1
Konstruktor yang dilindungi dan / atau internal akan menjadi sinyal seperti itu; konstruktor ini hanya akan tersedia untuk mengkonsumsi kode apakah dalam subkelas atau dalam rakitan yang sama. C # tidak memiliki kombinasi kata kunci untuk "protected dan internal" yang berarti hanya subtipe dalam majelis yang dapat menggunakannya, tetapi MSIL memiliki pengidentifikasi ruang lingkup untuk jenis visibilitas tersebut sehingga dapat dibayangkan spesifikasi C # dapat diperluas untuk menyediakan cara untuk menggunakannya . Tapi, ini benar-benar tidak ada hubungannya dengan penggunaan pabrik (kecuali jika Anda menggunakan pembatasan visibilitas untuk menegakkan penggunaan pabrik).
KeithS
2
Jawaban sempurna. Tepat pada bagian 'teori memenuhi kenyataan'. Pikirkan berapa ribu pengembang dan waktu manusia yang dihabiskan untuk memuji, membenarkan, menerapkan, menggunakan mereka untuk kemudian jatuh ke situasi yang sama seperti yang Anda gambarkan, hanya menjengkelkan. Mengikuti YAGNI, Ive tidak pernah mengidentifikasi perlunya menerapkan pabrik
Breno Salgado
Saya sedang pemrograman pada basis kode di mana karena implementasi OOP tidak memungkinkan overloading konstruktor, penggunaan konstruktor publik secara efektif dilarang. Ini sudah merupakan masalah kecil dalam bahasa yang memungkinkannya. Seperti menciptakan suhu. Fahrenheit dan Celcius keduanya mengapung. Namun Anda dapat mengotaknya, lalu masalah dipecahkan.
jgmjgm
33

Konstruktor baik-baik saja ketika mengandung pendek, kode sederhana.

Ketika inisialisasi menjadi lebih dari menetapkan beberapa variabel ke bidang, pabrik masuk akal. Berikut ini beberapa manfaatnya:

  • Panjang, kode rumit lebih masuk akal di kelas khusus (pabrik). Jika kode yang sama dimasukkan ke dalam konstruktor yang memanggil banyak metode statis, ini akan mencemari kelas utama.

  • Dalam beberapa bahasa dan beberapa kasus, melempar pengecualian pada konstruktor adalah ide yang sangat buruk , karena dapat menimbulkan bug.

  • Saat Anda memanggil konstruktor, Anda, pemanggil, perlu mengetahui jenis persis dari instance yang ingin Anda buat. Ini tidak selalu terjadi (sebagai Feeder, saya hanya perlu membuat Animaluntuk memberi makan; Saya tidak peduli apakah itu a Dogatau a Cat).

Arseni Mourzenko
sumber
2
Pilihannya bukan hanya "pabrik" atau "konstruktor." A Feedermungkin tidak menggunakan keduanya, dan sebaliknya memanggil metode Kennelobjek itu getHungryAnimal.
DougM
4
+1 Saya menemukan bahwa mematuhi aturan yang sama sekali tidak ada logika dalam konstruktor bukanlah ide yang buruk. Konstruktor hanya boleh digunakan untuk mengatur keadaan awal objek dengan menetapkan nilai argumennya ke variabel instan. Jika diperlukan sesuatu yang lebih rumit, paling tidak buat metode pabrik (kelas) untuk membangun instance.
KaptajnKold
Ini adalah satu-satunya jawaban yang memuaskan yang saya lihat di sini, menyelamatkan saya dari keharusan menulis sendiri. Jawaban lainnya hanya berurusan dengan konsep abstrak.
TheCatWhisperer
Tetapi argumen ini dapat dianggap sah Builder Patternjuga. Bukan?
soufrk
Aturan konstruktor
Breno Salgado
10

Jika Anda bekerja dengan antarmuka maka Anda dapat tetap independen dari implementasi yang sebenarnya. Pabrik dapat dikonfigurasikan (melalui properti, parameter atau metode lain) untuk membuat instantiate salah satu dari sejumlah implementasi yang berbeda.

Satu contoh sederhana: Anda ingin berkomunikasi dengan perangkat tetapi Anda tidak tahu apakah itu akan melalui Ethernet, COM atau USB. Anda mendefinisikan satu antarmuka dan 3 implementasi. Saat runtime Anda kemudian dapat memilih metode mana yang Anda inginkan dan pabrik akan memberi Anda implementasi yang sesuai.

Sering menggunakannya ...

paul
sumber
5
Saya akan menambahkan bahwa itu bagus untuk digunakan ketika ada beberapa implementasi antarmuka dan kode panggilan tidak atau tidak harus tahu mana yang harus dipilih. Tetapi ketika metode pabrik hanyalah pembungkus statis di sekitar konstruktor tunggal seperti dalam pertanyaan, itu adalah anti-pola. Ada harus beberapa implementasi dari yang untuk memilih atau pabrik mendapatkan di jalan dan menambahkan kompleksitas yang tidak perlu.
Sekarang Anda memiliki fleksibilitas tambahan dan secara teori aplikasi Anda dapat menggunakan Ethernet, COM, USB dan serial, siap untuk fireloop atau apa pun, secara teori. Pada kenyataannya aplikasi Anda hanya akan berkomunikasi melalui Ethernet .... pernah.
Pieter B
7

Ini adalah gejala keterbatasan dalam sistem modul Java / C #.

Pada prinsipnya, tidak ada alasan Anda tidak dapat menukar satu implementasi dari kelas dengan yang lain dengan konstruktor dan tanda tangan metode yang sama. Ada yang bahasa yang memungkinkan ini. Namun, Java dan C # bersikeras bahwa setiap kelas memiliki pengidentifikasi unik (nama yang sepenuhnya memenuhi syarat) dan kode klien berakhir dengan ketergantungan kode keras di atasnya.

Anda dapat semacam mendapatkan sekitar ini dengan mengutak-atik sistem file dan opsi compiler sehingga com.example.Foopeta ke file yang berbeda, tapi ini mengejutkan dan unintuitive. Bahkan jika Anda melakukannya, kode Anda masih terikat hanya pada satu implementasi kelas. Yaitu Jika Anda menulis kelas Fooyang tergantung pada kelas MySet, Anda dapat memilih implementasi MySetpada waktu kompilasi tetapi Anda masih tidak dapat instantiate Foomenggunakan dua implementasi yang berbeda dari MySet.

Keputusan desain yang tidak menguntungkan ini memaksa orang untuk menggunakan interfacekode yang tidak perlu untuk membuktikan kode mereka di masa depan terhadap kemungkinan bahwa mereka nantinya akan membutuhkan implementasi sesuatu yang berbeda, atau untuk memfasilitasi pengujian unit. Ini tidak selalu layak; jika Anda memiliki metode apa pun yang melihat bidang pribadi dari dua instance kelas, tidak akan dapat mengimplementasikannya dalam sebuah antarmuka. Karena itulah, misalnya, Anda tidak melihat antarmuka unionJava Set. Namun, di luar tipe dan koleksi numerik, metode biner tidak umum, jadi Anda biasanya bisa lolos begitu saja.

Tentu saja, jika Anda menelepon new Foo(...)Anda masih memiliki ketergantungan pada kelas , maka Anda memerlukan pabrik jika Anda ingin kelas dapat membuat instantiate antarmuka secara langsung. Namun, biasanya ide yang lebih baik untuk menerima contoh di konstruktor dan membiarkan orang lain memutuskan implementasi yang akan digunakan.

Terserah Anda untuk memutuskan apakah perlu membengkak basis kode Anda dengan antarmuka dan pabrik. Di satu sisi, jika kelas yang dimaksud adalah internal ke basis kode Anda, refactoring kode sehingga menggunakan kelas yang berbeda atau antarmuka di masa depan adalah sepele; Anda bisa memanggil YAGNI dan refactor nanti jika situasinya muncul. Tetapi jika kelas adalah bagian dari API publik dari perpustakaan yang telah Anda terbitkan, Anda tidak memiliki opsi untuk memperbaiki kode klien. Jika Anda tidak menggunakan interfacedan kemudian membutuhkan beberapa implementasi, Anda akan terjebak di antara batu dan tempat yang sulit.

Doval
sumber
2
Saya berharap Java dan turunannya seperti .NET memiliki sintaks khusus untuk kelas yang membuat instance itu sendiri, dan sebaliknya newhanya menjadi sintaksis gula untuk memanggil metode statis bernama khusus (yang akan dihasilkan secara otomatis jika suatu tipe memiliki "konstruktor publik" "tetapi tidak secara eksplisit memasukkan metode). IMHO, jika kode hanya menginginkan hal standar yang membosankan yang diterapkan List, harus memungkinkan antarmuka untuk memberikannya tanpa klien harus mengetahui implementasi tertentu (misalnya ArrayList).
supercat
2

Menurut pendapat saya, mereka hanya menggunakan Pabrik Sederhana, yang bukan pola desain yang tepat dan tidak boleh bingung dengan Pabrik Abstrak atau Metode Pabrik.

Dan karena mereka telah menciptakan "kelas kain besar dengan ribuan metode statis CreateXXX", yang terdengar anti-pola (kelas Dewa mungkin?).

Saya pikir Pabrik Sederhana dan metode pembuat statis (yang tidak memerlukan kelas eksternal), dapat berguna dalam beberapa kasus. Misalnya, ketika konstruksi suatu objek memerlukan berbagai langkah seperti instancing objek lain (misalnya komposisi yang disukai).

Saya tidak akan menyebut bahkan menyebutnya Pabrik, tetapi hanya sekelompok metode yang dikemas dalam beberapa kelas acak dengan akhiran "Pabrik".

FranMowinckel
sumber
1
Pabrik Sederhana memiliki tempatnya. Bayangkan suatu entitas mengambil dua parameter konstruktor, int xdan IFooService fooService. Anda tidak ingin lewat di fooServicemana - mana, jadi Anda membuat pabrik dengan metode Create(int x)dan menyuntikkan layanan di dalam pabrik.
AlexFoxGill
4
@AlexG Dan kemudian, Anda harus berkeliling IFactorykemana saja IFooService.
Euforia
3
Saya setuju dengan Euforia; dalam pengalaman saya, objek yang dapat disuntikkan ke dalam grafik dari atas cenderung merupakan tipe yang dibutuhkan semua objek tingkat rendah, dan dengan demikian, melewatkan IFooServices di sekitar bukanlah masalah besar. Mengganti satu abstraksi dengan abstraksi yang lain tidak menghasilkan apa-apa selain mengaburkan basis kode.
KeithS
ini terlihat sama sekali tidak relevan dengan pertanyaan yang diajukan, "Mengapa saya harus menggunakan kelas pabrik alih-alih konstruksi objek langsung? Kapan saya harus menggunakan konstruktor publik, dan kapan saya harus menggunakan pabrik?" Lihat Bagaimana Menjawab
nyamuk
1
Itu hanya judul pertanyaan, saya pikir Anda melewatkan sisanya. Lihat titik tautan terakhir yang disediakan;).
FranMowinckel
1

Sebagai pengguna perpustakaan, jika perpustakaan memiliki metode pabrik, maka Anda harus menggunakannya. Anda akan berasumsi bahwa metode pabrik memberi penulis perpustakaan fleksibilitas untuk membuat perubahan tertentu tanpa mempengaruhi kode Anda. Misalnya mereka mungkin mengembalikan turunan dari beberapa subclass dalam metode pabrik, yang tidak akan bekerja dengan konstruktor sederhana.

Sebagai pencipta perpustakaan, Anda akan menggunakan metode pabrik jika Anda ingin menggunakan fleksibilitas itu sendiri.

Dalam kasus yang Anda jelaskan, Anda tampaknya memiliki kesan bahwa mengganti konstruktor dengan metode pabrik tidak ada gunanya. Itu tentu menyebalkan bagi semua orang yang terlibat; perpustakaan tidak boleh menghapus apa pun dari APInya tanpa alasan yang kuat. Jadi jika saya telah menambahkan metode pabrik, saya akan membiarkan konstruktor yang ada tersedia, mungkin sudah usang, sampai metode pabrik tidak hanya memanggil konstruktor itu lagi dan kode menggunakan konstruktor polos berfungsi kurang baik dari yang seharusnya. Kesan Anda mungkin benar.

gnasher729
sumber
Juga mencatat; Jika pengembang perlu menyediakan kelas turunan dengan fungsionalitas tambahan (properti ekstra, inisialisasi) pengembang dapat melakukannya. (dengan asumsi bahwa metode pabrik dapat ditimpa). Penulis API juga dapat menyediakan solusi untuk kebutuhan pelanggan khusus.
Eric Schneider
-4

Ini tampaknya sudah usang di zaman Scala dan pemrograman fungsional. Fondasi fungsi yang solid menggantikan trilyun kelas.

Juga perlu dicatat bahwa Java double {{tidak berfungsi lagi ketika menggunakan pabrik yaitu

someFunction(new someObject() {{
    setSomeParam(...);
    etc..
}})

Yang memungkinkan Anda membuat kelas anonim dan menyesuaikannya.

Dalam dilema ruang waktu faktor waktu sekarang sangat menyusut berkat CPU cepat sehingga pemrograman fungsional memungkinkan penyusutan ruang yaitu ukuran kode sekarang praktis.

Marc
sumber
2
ini lebih mirip komentar tangensial (lihat Bagaimana Menjawab ), dan sepertinya tidak menawarkan sesuatu yang substansial atas poin yang dibuat dan dijelaskan dalam 9 jawaban sebelumnya
nyamuk