Ano ang singleton sa Java?
Ang Singleton ay isa sa pinakasimpleng pattern ng disenyo sa antas ng klase. Minsan sinasabi ng mga tao na "singleton ang klase na ito", ibig sabihin, ipinapatupad ng klase ang pattern ng disenyo ng singleton. Minsan kinakailangan na magsulat ng klase kung saan nililimitahan natin ang instantiation sa isang bagay. Halimbawa, isang klase na responsable sa pag-log o pagkonekta sa isang database. Ang singleton design pattern ay naglalarawan kung paano natin ito makakamit. Ang singleton ay isang design pattern na gumagawa ng dalawang bagay:-
Tinitiyak nito na magkakaroon lamang ng isang pagkakataon ng klase.
-
Nagbibigay ito ng isang punto ng pandaigdigang pag-access sa pagkakataong iyon.
-
Isang pribadong constructor. Nililimitahan nito ang kakayahang lumikha ng mga bagay ng klase sa labas ng klase mismo.
-
Isang pampublikong static na pamamaraan na nagbabalik ng instance ng klase. Ang pamamaraang ito ay tinatawag na getInstance . Ito ang punto ng pandaigdigang pag-access sa instance ng klase.
Mga opsyon sa pagpapatupad
Ang pattern ng disenyo ng singleton ay inilalapat sa iba't ibang paraan. Ang bawat pagpipilian ay mabuti at masama sa sarili nitong paraan. Gaya ng dati, walang perpektong opsyon dito, ngunit dapat tayong magsikap para sa isa. Una sa lahat, magpasya tayo kung ano ang bumubuo ng mabuti at masama, at kung anong mga sukatan ang nakakaapekto sa kung paano natin tinatasa ang iba't ibang pagpapatupad ng pattern ng disenyo. Magsimula tayo sa mabuti. Narito ang mga salik na ginagawang mas makatas at kaakit-akit ang pagpapatupad:-
Lazy initialization: hindi nagagawa ang instance hangga't hindi ito kinakailangan.
-
Simple at transparent na code: ang panukat na ito, siyempre, ay subjective, ngunit ito ay mahalaga.
-
Kaligtasan ng thread: tamang operasyon sa isang multi-threaded na kapaligiran.
-
Mataas na pagganap sa isang multi-threaded na kapaligiran: kaunti o walang pag-block ng thread kapag nagbabahagi ng mapagkukunan.
-
Walang tamad na pagsisimula: kapag ang klase ay na-load kapag nagsimula ang aplikasyon, hindi alintana kung ito ay kinakailangan o hindi (paradoxically, sa IT mundo mas mahusay na maging tamad)
-
Kumplikado at mahirap basahin ang code. Ang sukatan na ito ay subjective din. Kung magsisimulang dumugo ang iyong mga mata, ipagpalagay namin na ang pagpapatupad ay hindi ang pinakamahusay.
-
Kakulangan ng kaligtasan ng thread. Sa madaling salita, "panganib sa thread". Maling operasyon sa isang multi-threaded na kapaligiran.
-
Hindi magandang pagganap sa isang multi-threaded na kapaligiran: ang mga thread ay humaharang sa bawat isa sa lahat ng oras o madalas kapag nagbabahagi ng mapagkukunan.
Code
Ngayon handa na kaming isaalang-alang ang iba't ibang mga opsyon sa pagpapatupad at ipahiwatig ang mga kalamangan at kahinaan:Simple
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
Ang pinakasimpleng pagpapatupad. Mga kalamangan:
-
Simple at transparent na code
-
Kaligtasan ng thread
-
Mataas na pagganap sa isang multi-threaded na kapaligiran
- Walang tamad na pagsisimula.
Tamad na pagsisimula
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Mga kalamangan:
-
Tamad na pagsisimula.
-
Hindi ligtas sa thread
Naka-synchronize na pag-access
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Mga kalamangan:
-
Tamad na pagsisimula.
-
Kaligtasan ng thread
-
Hindi magandang pagganap ng multithreaded
I-double check ang pag-lock
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
Mga kalamangan:
-
Tamad na pagsisimula.
-
Kaligtasan ng thread
-
Mataas na pagganap sa isang multi-threaded na kapaligiran
-
Hindi suportado sa mga naunang bersyon ng Java na mas mababa sa 1.5 (ang paggamit ng pabagu-bagong keyword ay naayos mula noong 1.5 na bersyon)
May hawak ng klase
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}
Mga kalamangan:
-
Tamad na pagsisimula.
-
Kaligtasan ng thread.
-
Mataas na pagganap sa isang multi-threaded na kapaligiran.
-
Ang tamang operasyon ay nangangailangan ng garantiya na ang singleton object ay sinisimulan nang walang mga error. Kung hindi, ang unang tawag sa getInstance na paraan ay magreresulta sa isang ExceptionInInitializerError , at lahat ng kasunod na tawag ay magbubunga ng NoClassDefFoundError .
Pagpapatupad | Tamad na pagsisimula | Kaligtasan ng thread | Multithreaded na pagganap | Kailan gagamitin? |
---|---|---|---|---|
Simple | - | + | Mabilis | Hindi kailanman. O posibleng kapag ang tamad na pagsisimula ay hindi mahalaga. Ngunit hindi kailanman magiging mas mahusay. |
Tamad na pagsisimula | + | - | Hindi maaari | Laging kapag hindi kailangan ang multithreading |
Naka-synchronize na pag-access | + | + | Mabagal | Hindi kailanman. O posibleng kapag ang multithreaded na pagganap ay hindi mahalaga. Ngunit hindi kailanman magiging mas mahusay. |
I-double check ang pag-lock | + | + | Mabilis | Sa mga bihirang kaso kapag kailangan mong pangasiwaan ang mga exception kapag lumilikha ng singleton (kapag hindi naaangkop ang singleton na may hawak ng klase) |
May hawak ng klase | + | + | Mabilis | Sa tuwing kailangan ang multithreading at may garantiya na malilikha ang singleton object nang walang problema. |
Mga kalamangan at kahinaan ng singleton pattern
Sa pangkalahatan, ginagawa ng isang singleton ang eksaktong inaasahan dito:-
Tinitiyak nito na magkakaroon lamang ng isang pagkakataon ng klase.
-
Nagbibigay ito ng isang punto ng pandaigdigang pag-access sa pagkakataong iyon.
-
Ang singleton ay lumalabag sa iisang responsibilidad na prinsipyo: bilang karagdagan sa mga direktang tungkulin nito, kinokontrol din ng singleton class ang bilang ng mga pagkakataon.
-
Ang pag-asa ng isang ordinaryong klase sa isang singleton ay hindi makikita sa pampublikong kontrata ng klase.
-
Ang mga global variable ay masama. Sa huli, ang isang singleton ay nagiging isang mabigat na global variable.
-
Ang pagkakaroon ng singleton ay binabawasan ang testability ng application sa kabuuan at ang mga klase na gumagamit ng singleton sa partikular.