Apa metode pabrik statis?

261

Apa itu metode "pabrik statis"?

freddiefujiwara
sumber
Metode pabrik statis alternatif menggunakan injeksi ketergantungan.
CMCDragonkai
1
@ThangPham Jawaban Jason Owen cacat karena dimaksudkan untuk berbicara tentang pola Metode Pabrik, yang sangat berbeda dari pola metode pabrik statis yang sebenarnya dibicarakan. Jadi, sementara itu melakukan pekerjaan yang baik untuk menjawab pertanyaan yang sebenarnya, saya tidak berpikir itu bisa diterima dalam keadaan saat ini, karena itu membawa dalam pola yang tidak berhubungan dan meningkatkan kebingungan yang sudah sangat umum tentang perbedaan antara kedua pola.
Theodore Murdock
@ CMCDragonkai Saya pikir injeksi ketergantungan dan pabrik statis berbeda. Pabrik statis mungkin diperlukan bahkan dalam kasus injeksi ketergantungan untuk instantiasi ketergantungan yang akan disuntikkan.
Karan Khanna

Jawaban:

126

Kami menghindari memberikan akses langsung ke koneksi basis data karena sumber daya yang intensif. Jadi kami menggunakan metode pabrik statis getDbConnectionyang membuat koneksi jika kami di bawah batas. Kalau tidak, ia mencoba untuk menyediakan koneksi "cadangan", gagal dengan pengecualian jika tidak ada.

public class DbConnection{
   private static final int MAX_CONNS = 100;
   private static int totalConnections = 0;

   private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();

   private DbConnection(){
     // ...
     totalConnections++;
   }

   public static DbConnection getDbConnection(){

     if(totalConnections < MAX_CONNS){
       return new DbConnection();

     }else if(availableConnections.size() > 0){
         DbConnection dbc = availableConnections.iterator().next();
         availableConnections.remove(dbc);
         return dbc;

     }else {
         throw new NoDbConnections();
     }
   }

   public static void returnDbConnection(DbConnection dbc){
     availableConnections.add(dbc);
     //...
   }
}
Matthew Flaschen
sumber
jika saya mengerti benar, dapatkah Anda menambahkan availableConnections.add (db) ke metode returnDbConnection (DbConnection db)?
Haifeng Zhang
@haifzhan, itu tidak benar-benar dimaksudkan untuk lengkap, tapi oke.
Matthew Flaschen
@MatthewFlaschen juga haruskah total koneksi dikurangi saat koneksi dikembalikan?
batu bergulir
@Ridhar, tidak, ini adalah jumlah koneksi yang ada (dilacak sehingga lebih dari MAX_CONNS tidak dibuat), bukan nomor yang beredar.
Matthew Flaschen
@MatthewFlaschen metode Anda akan ditangkap oleh sonarcube sebagai pemblokir-bug jika DbConnection Closeable.
Awan Biru
477

The Pola metode pabrik statis adalah cara untuk penciptaan encapsulate objek. Tanpa metode pabrik, Anda hanya akan memanggil kelas itu konstruktor langsung: Foo x = new Foo(). Dengan pola ini, Anda malah akan memanggil metode pabrik: Foo x = Foo.create(). Konstruktor ditandai pribadi, sehingga mereka tidak dapat dipanggil kecuali dari dalam kelas, dan metode pabrik ditandai staticsehingga dapat dipanggil tanpa terlebih dahulu memiliki objek.

Ada beberapa keuntungan dari pola ini. Pertama adalah bahwa pabrik dapat memilih dari banyak subclass (atau pelaksana antarmuka) dan mengembalikannya. Dengan cara ini penelepon dapat menentukan perilaku yang diinginkan melalui parameter, tanpa harus mengetahui atau memahami hierarki kelas yang berpotensi kompleks.

Keuntungan lain adalah, seperti yang ditunjukkan Matius dan James, mengendalikan akses ke sumber daya terbatas seperti koneksi. Ini cara untuk menerapkan kumpulan objek yang dapat digunakan kembali - alih-alih membangun, menggunakan, dan menghancurkan objek, jika konstruksi dan penghancuran adalah proses yang mahal, mungkin lebih masuk akal untuk membangunnya sekali dan mendaur ulangnya. Metode pabrik dapat mengembalikan objek instantiated yang ada dan tidak terpakai jika memiliki satu, atau membangun satu jika objek menghitung di bawah beberapa ambang bawah, atau melemparkan pengecualian atau kembali nulljika itu di atas ambang atas.

Sesuai artikel di Wikipedia, beberapa metode pabrik juga memungkinkan interpretasi yang berbeda dari tipe argumen yang serupa. Biasanya konstruktor memiliki nama yang sama dengan kelas, yang berarti Anda hanya dapat memiliki satu konstruktor dengan tanda tangan yang diberikan . Pabrik tidak dibatasi, yang berarti Anda dapat memiliki dua metode berbeda yang menerima jenis argumen yang sama:

Coordinate c = Coordinate.createFromCartesian(double x, double y)

dan

Coordinate c = Coordinate.createFromPolar(double distance, double angle)

Ini juga dapat digunakan untuk meningkatkan keterbacaan, seperti yang dicatat oleh Rasmus.

Jason Owen
sumber
32
Perhatikan bahwa metode pabrik statis tidak sama dengan pola Metode Pabrik dari Pola Desain [Gamma95, hal. 107]. Metode pabrik statis yang dijelaskan dalam item ini tidak memiliki padanan langsung dalam Pola Desain.
Josh Sunshine
Imbalan bagi saya untuk jawaban ini adalah referensi ke objek poolable. Ini adalah PERSIS bagaimana saya menggunakan pola metode pabrik. Metode pabrik disediakan untuk membantu mengendalikan siklus hidup suatu objek: "membuat" baik menarik objek dari kolam atau membuat contoh baru jika kolam kosong, "menghancurkan" mengembalikannya ke kolam untuk digunakan kembali di masa depan.
MutantXenu
2
Anda harus benar-benar menggunakan "pola metode pabrik statis" di mana pun Anda mengatakan "pola metode pabrik" di pos ini, Anda menggunakan istilah yang salah. Selain itu, Anda menautkan ke artikel Wikipedia dengan pola yang berbeda dari pola yang Anda bicarakan. Pola Factory Method mungkin seharusnya disebut pola "Factory Interface", karena melibatkan penggunaan beberapa objek pabrik yang mengimplementasikan antarmuka pabrik untuk memungkinkan algoritma tunggal untuk menghasilkan serta bekerja dengan instance antarmuka, dengan menerima objek pabrik yang dapat menghasilkan subclass yang diinginkan spesifik.
Theodore Murdock
8
Saya setuju dengan @TheodoreMurdock. Anda menggunakan istilah yang salah. Apa yang Anda bicarakan adalah Joshua Bloch "Static Factory Method" tetapi Anda menggunakan istilah "Factory Method Pattern" dari GoF. Harap edit agar orang lain tidak salah paham.
emeraldhieu
1
Perhatikan bahwa konstruktor tidak harus bersifat pribadi. Kelas dapat menyediakan metode dan konstruktor pabrik statis publik.
Kevin
171

CATATAN! "The metode pabrik statis adalah TIDAK sama dengan Pabrik Metode pola" (c) Jawa Efektif, Joshua Bloch.

Metode Pabrik: "Tentukan antarmuka untuk membuat objek, tetapi biarkan kelas yang mengimplementasikan antarmuka memutuskan kelas mana yang akan dipakai. Metode Pabrik memungkinkan kelas menunda instantiasi ke subclass" (c) GoF.

"Metode pabrik statis hanyalah metode statis yang mengembalikan instance kelas." (c) Java Efektif, Joshua Bloch. Biasanya metode ini ada di dalam kelas tertentu.

Perbedaan:

Gagasan kunci metode pabrik statis adalah untuk mendapatkan kontrol atas pembuatan objek dan mendelegasikannya dari konstruktor ke metode statis. Keputusan objek yang akan dibuat adalah seperti di Pabrik Abstrak dibuat di luar metode (dalam kasus umum, tetapi tidak selalu). Sedangkan ide kunci (!) Dari Metode Pabrik adalah untuk mendelegasikan keputusan instance kelas apa yang akan dibuat di dalam Metode Pabrik. Misalnya implementasi Singleton klasik adalah kasus khusus metode pabrik statis. Contoh metode statis yang umum digunakan:

  • Nilai dari
  • dapatkanInstance
  • Instance baru
Grygoriy Gonchar
sumber
Bisakah Anda memberi tahu saya perbedaan antara A () baru dan A.newInstance ()? dan di dalam A.newInstance apa yang harus kita lakukan?
Shen
69

Keterbacaan dapat ditingkatkan dengan metode pabrik statis:

Membandingkan

public class Foo{
  public Foo(boolean withBar){
    //...
  }
}

//...

// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.

untuk

public class Foo{
  public static Foo createWithBar(){
    //...
  }

  public static Foo createWithoutBar(){
    //...
  }
}

// ...

// This is much easier to read!
Foo foo = Foo.createWithBar();
Rasmus Faber
sumber
Jadi saya mencoba menerapkan contoh Anda tetapi saya tidak yakin bagaimana ini bekerja. Apakah dua metode createWithBar dan createWithoutBar seharusnya memanggil 2 konstruktor pribadi di dalam kelas Foo?
Essej
@ Baxtex: Ya. Masing-masing akan memanggil konstruktor pribadi. Mungkin hanya yang sama: private Foo(boolean withBar){/*..*/} public static Foo createWithBar(){return new Foo(true);} public static Foo createWithoutBar(){return new Foo(false);}
Rasmus Faber
Saya pikir ini bukan "skala" dengan sangat baik. Jika Anda memiliki tiga atau lebih parameter, bagaimana Anda bisa menggunakan ide ini dan membuat nama yang bagus untuk metode ini?
Dherik
@ Dherik: Maka Anda mungkin harus menggunakan pola builder sebagai gantinya: new FooBuilder (). WithBar (). WithoutFoo (). WithBaz (). Build ();
Rasmus Faber
21
  • memiliki nama, tidak seperti konstruktor, yang dapat mengklarifikasi kode.
  • tidak perlu membuat objek baru pada setiap doa - objek dapat di-cache dan digunakan kembali, jika perlu.
  • dapat mengembalikan subtipe jenis pengembaliannya - khususnya, dapat mengembalikan objek yang kelas implementasinya tidak diketahui oleh penelepon. Ini adalah fitur yang sangat berharga dan banyak digunakan dalam banyak kerangka kerja yang menggunakan antarmuka sebagai jenis pengembalian metode pabrik statis.

dari http://www.javapractices.com/topic/TopicAction.do?Id=21

tentara
sumber
18

Itu semua bermuara pada rawatan. Cara terbaik untuk menempatkan ini adalah setiap kali Anda menggunakan newkata kunci untuk membuat objek, Anda menyambungkan kode yang Anda tulis ke implementasi.

Pola pabrik memungkinkan Anda memisahkan cara Anda membuat objek dari apa yang Anda lakukan dengan objek. Ketika Anda membuat semua objek Anda menggunakan konstruktor, Anda pada dasarnya mengkabel kode yang menggunakan objek untuk implementasi itu. Kode yang menggunakan objek Anda "tergantung pada" objek itu. Ini mungkin tidak tampak seperti masalah besar di permukaan, tetapi ketika objek berubah (pikirkan untuk mengubah tanda tangan konstruktor, atau subklasifikasi objek), Anda harus kembali dan memperbaiki hal-hal di mana-mana.

Saat ini pabrik-pabrik sebagian besar telah disisihkan untuk menggunakan Injeksi Ketergantungan karena mereka memerlukan banyak kode pelat-ketel yang ternyata agak sulit untuk dipertahankan sendiri. Ketergantungan Injeksi pada dasarnya setara dengan pabrik tetapi memungkinkan Anda untuk menentukan bagaimana benda Anda dihubungkan bersama secara deklaratif (melalui konfigurasi atau anotasi).

cwash
sumber
3
Apakah Anda mengatakan bahwa pabrik memerlukan dana talangan? ;)
John Farrell
4
Ha ha! Di hari ini dan usia saya pikir kita semua bisa menggunakan bailout ... :)
cwash
11

Jika konstruktor suatu kelas bersifat pribadi maka Anda tidak dapat membuat objek untuk kelas dari luarnya.

class Test{
 int x, y;
 private Test(){
  .......
  .......
  }
}

Kami tidak dapat membuat objek untuk kelas di atas dari luarnya. Jadi Anda tidak dapat mengakses x, y dari luar kelas. Lalu apa gunanya kelas ini?
Inilah Jawabannya: metode PABRIK .
Tambahkan metode di bawah ini di kelas di atas

public static Test getObject(){
  return new Test();
}

Jadi sekarang Anda bisa membuat objek untuk kelas ini dari luarnya. Seperti jalan ...

Test t = Test.getObject();

Oleh karena itu, metode statis yang mengembalikan objek kelas dengan mengeksekusi konstruktor pribadinya disebut sebagai metode PABRIK
.

Santhosh
sumber
1
Mengapa Anda menyebutnya "solusi"? Mendeklarasikan konstruktor pribadi bukanlah "masalah", Ini adalah pola desain.
Ojonugwa Jude Ochalifu
1
Diperbarui. Terima kasih
Santhosh
HaiSantosh Saya prihatin mengapa Anda tidak membiarkan konstruktor pribadi ini publik? Jika Anda tidak ingin membuat subclass, itu baik untuk saya, tetapi jika saya tidak bermaksud membuat konstruktor pribadi, apakah kita mendapat manfaat Static Factory Methodlebih dari konstruktor publik?
Shen
9

Saya pikir saya akan menambahkan beberapa cahaya ke posting ini pada apa yang saya tahu. Kami menggunakan teknik ini secara ekstensif di kami recent android project. Alih-alih creating objects using new operatorAnda juga dapat menggunakan static methoduntuk membuat instance kelas. Daftar kode:

//instantiating a class using constructor
Vinoth vin = new Vinoth(); 

//instantiating the class using static method
Class Vinoth{
  private Vinoth(){
  }
  // factory method to instantiate the class
  public static Vinoth getInstance(){
    if(someCondition)
        return new Vinoth();
  }
}

Metode statis mendukung pembuatan objek bersyarat : Setiap kali Anda memanggil konstruktor, objek akan dibuat tetapi Anda mungkin tidak menginginkannya. misalkan Anda ingin memeriksa beberapa kondisi hanya kemudian Anda ingin membuat objek baru. Anda tidak akan membuat instance baru dari Vinoth setiap kali, kecuali jika kondisi Anda terpenuhi.

Contoh lain diambil dari Java Efektif .

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
}

Metode ini menerjemahkan nilai primitif boolean menjadi referensi objek Boolean. The Boolean.valueOf(boolean)Metode menggambarkan kita, tidak pernah menciptakan sebuah objek. Kemampuan static factory methodsuntuk mengembalikan objek yang sama dari pengulangan invocationsmemungkinkan kelas untuk mempertahankan kontrol ketat atas instance yang ada kapan saja.

Static factory methods tidak seperti itu constructors , mereka dapat mengembalikan salah objectsatu subtypedari tipe pengembalian mereka. Salah satu aplikasi fleksibilitas ini adalah API dapat mengembalikan objek tanpa membuat kelasnya publik. Menyembunyikan kelas implementasi dengan cara ini mengarah ke API yang sangat kompak.

Calendar.getInstance () adalah contoh yang bagus untuk hal di atas, Ini membuat tergantung pada lokal a BuddhistCalendar , JapaneseImperialCalendaratau secara default Georgian.

Contoh lain yang bisa saya pikirkan adalah Singleton pattern, di mana Anda membuat konstruktor pribadi membuat getInstancemetode sendiri di mana Anda memastikan, bahwa selalu ada hanya satu contoh yang tersedia.

public class Singleton{
    //initailzed during class loading
    private static final Singleton INSTANCE = new Singleton();

    //to prevent creating another instance of Singleton
    private Singleton(){}

    public static Singleton getSingleton(){
        return INSTANCE;
    }
}
Thalaivar
sumber
4

Metode pabrik, metode yang mengabstraksi instantiasi objek. Umumnya pabrik berguna ketika Anda tahu bahwa Anda memerlukan instance baru dari kelas yang mengimplementasikan beberapa antarmuka tetapi Anda tidak tahu kelas pelaksana.

Ini berguna ketika bekerja dengan hierarki kelas terkait, contoh yang baik dari ini adalah toolkit GUI. Anda dapat dengan mudah membuat kode panggilan ke konstruktor untuk implementasi konkret dari setiap widget, tetapi jika Anda ingin menukar satu toolkit dengan yang lain, Anda akan memiliki banyak tempat untuk diubah. Dengan menggunakan pabrik, Anda mengurangi jumlah kode yang perlu Anda ubah.

Bryan Kyle
sumber
Dengan asumsi Anda memiliki pabrik Anda mengembalikan jenis antarmuka, dan bukan kelas konkret yang Anda hadapi.
Bill Lynch
1
Jawaban ini adalah tentang pola desain metode pabrik bukan metode pabrik statis. Metode pabrik statis hanyalah metode statis publik yang mengembalikan instance kelas. Lihat Bab 2 Jawa Efektif untuk perincian lebih lanjut.
Josh Sunshine
4

Salah satu keuntungan yang berasal dari pabrik Static adalah bahwa API dapat mengembalikan objek tanpa membuat kelas mereka publik. Ini mengarah ke API yang sangat ringkas. Di java ini dicapai oleh kelas Koleksi yang menyembunyikan sekitar 32 kelas yang membuatnya koleksi API sangat kompak.

Rakesh Chauhan
sumber
2

Metode pabrik statis baik ketika Anda ingin memastikan bahwa hanya satu instance tunggal akan mengembalikan kelas beton untuk digunakan.

Misalnya, dalam kelas koneksi database, Anda mungkin ingin hanya satu kelas membuat koneksi database, sehingga jika Anda memutuskan untuk beralih dari Mysql ke Oracle Anda hanya dapat mengubah logika dalam satu kelas, dan sisa aplikasi akan gunakan koneksi baru.

Jika Anda ingin menerapkan penggabungan basis data, maka itu juga akan dilakukan tanpa mempengaruhi aplikasi lainnya.

Ini melindungi sisa aplikasi dari perubahan yang mungkin Anda lakukan pada pabrik, yang merupakan tujuannya.

Alasannya statis adalah jika Anda ingin melacak sumber daya terbatas (jumlah koneksi soket atau file menangani) maka kelas ini dapat melacak berapa banyak yang telah pingsan dan dikembalikan, sehingga Anda tidak menghabiskan sumber daya terbatas.

James Black
sumber
2

Salah satu keuntungan dari metode pabrik statis dengan konstruktor pribadi (pembuatan objek harus dibatasi untuk kelas eksternal untuk memastikan instance tidak dibuat secara eksternal) adalah Anda dapat membuat kelas yang dikendalikan oleh instance . Dan kelas yang dikendalikan oleh instance menjamin bahwa tidak ada dua instance berbeda yang sama ada ( a.equals (b) jika dan hanya jika a == b ) selama program Anda berjalan yang berarti Anda dapat memeriksa kesetaraan objek dengan operator == alih-alih metode yang sama , menurut java Efektif.

Kemampuan metode pabrik statis untuk mengembalikan objek yang sama dari pemanggilan berulang memungkinkan kelas untuk mempertahankan kontrol ketat atas kejadian apa saja yang ada setiap saat. Kelas yang melakukan ini dikatakan dikendalikan oleh instance. Ada beberapa alasan untuk menulis kelas yang dikendalikan oleh instance. Kontrol Instance memungkinkan kelas untuk menjamin bahwa itu adalah singleton (Item 3) atau noninstantiable (Item 4). Juga, ini memungkinkan kelas yang tidak dapat diubah (Butir 15) untuk membuat jaminan bahwa tidak ada dua instance yang sama ada: a.equals (b) jika dan hanya jika a == b. Jika suatu kelas membuat jaminan ini, maka kliennya dapat menggunakan operator == alih-alih metode equals (Object), yang dapat menghasilkan peningkatan kinerja. Jenis Enum (Item 30) memberikan jaminan ini.

Dari Java Efektif, Joshua Bloch (Item 1, halaman 6)

SherlockHomeless
sumber
1

statis

Seorang anggota menyatakan dengan kata kunci 'statis'.

metode pabrik

Metode yang membuat dan mengembalikan objek baru.

di Jawa

Bahasa pemrograman relevan dengan arti 'statis' tetapi tidak dengan definisi 'pabrik'.

Marquis dari Lorne
sumber
@Victor Responses tidak perlu mengandung argumen. Fakta harus memadai: jika kontroversial, mereka dapat didukung oleh argumen atau kutipan. Saya tidak sadar ada sesuatu yang kontroversial di sini.
Marquis of Lorne
Saya menyatakan bahwa karena jawabannya terlalu pendek dan benar-benar tidak dipahami dengan baik pada pandangan pertama, kedua dan ketiga, bagaimanapun juga tergantung pada OP untuk bertanya kembali. Nevermind, saya telah berubah pikiran dan mencoba untuk menghapus downvote, tetapi saya tidak bisa.
Victor
@ Viktor Tentukan 'terlalu pendek'. Terkadang jawaban yang sebenarnya adalah 'ya', 'tidak', 'tidak', atau 'keduanya'. 'Terlalu pendek' sepenuhnya subjektif. Saya masih tidak mengerti komentar asli Anda. Anda tidak perlu argumen untuk mendukung definisi. Menurut definisi. Saya telah mengedit jawaban saya sehingga sekarang mungkin untuk menghapus downvote.
Marquis of Lorne
Tentu saja subyektif ... semua jawaban stackoverflow bersifat subyektif, pada kenyataannya mereka terkait dengan tingkat pengetahuan penulis dan kemauan untuk menjawab. Saya benar-benar tidak mengerti jawaban Anda, mungkin terlalu pendek.
Victor
@Victor Rubbish. Masalah-masalah fakta tidak subyektif, dan tidak ada hal-hal yang dapat diturunkan secara inferior dari fakta atau aksioma. 'Terlalu pendek' di sisi lain adalah subyektif, dan saya sudah membahasnya. Jawaban ini pada dasarnya sama dengan yang ini , yang belum Anda komentari. Komentar Anda tetap tidak jelas.
Marquis of Lorne
1

Implementasi Java berisi kelas-kelas utilitas java.util.Arrays dan java.util.Collections keduanya mengandung metode pabrik statis , contohnya, dan cara menggunakan:

Juga kelas java.lang.String memiliki metode pabrik statis seperti :

  • String.format(...), String.valueOf(..), String.copyValueOf(...)
Владимир Дворник
sumber