私有建構函式的應用與靜態工廠模式
在Java中,建構函式的訪問級別通常是public, 它提供了一個構造該類物件的介面。可是你知不知道,把建構函式的級別設為private, 有一些特別用處。
先來看一段程式碼:
//Shape.java
public class Shape {
private Shape() {
}
public static Shape makeShape() {
System.out.println("here is the shape you ordered");
return (new Shape());
}
public static void main(String args[]) {
Shape.makeShape();
}
}
首先從語言角度分析,我們可以知道, 任何類的使用者都無法使用建構函式來生成一個圖形, 因為建構函式是私有的,無法被類以外的函式使用。而只能通過呼叫makeShape來實現。
也許你會問,為什麼不直接使用建構函式來生成圖形,而需要使用一個看上去多餘的makeShape方法呢?
這樣做有以下幾個好處:
1。你可以返回任何的Shape型別,包括Shape的子類。比如你可以把makeShape寫成這樣:
public static Shape makeShape() {
System.out.println("here is the shape you ordered");
if (retangle)
return (new Retangle());
if (Circle)
return (new Circle());
}
這裡假設Retangle 和 Circle 都是shape的子類,並且和Shape類在同一個包內,Shape類可以訪問子類的建構函式。這樣shape就提供了一個圖形工廠。使用者通過一個介面就可以生成不同的圖形。事實上,這種用法被稱為“工廠模式”。
2。可以實現一個類只有一個物件。請看下面的程式碼
//Handler.java
public class Handler {
private Handler handler = null;
private Handler() {
}
public static getHandler() {
if (!handler)
handler = new Handler();
return handler;
}
public static void main(String args[]) {
Handler.getHandler();
}
}
當handlerw為空時,那麼重新構造一個handler,然後返回;如果已經構造過了,那麼就直接返回已經存在的handler。這種用法被稱為“Singleton pattern". 如果直接使用建構函式來構造物件,那麼你就無法控制生成的數量。在實際應用中,往往會做一些改變。比如使用一個具有一定容量的池,當需要構造一個物件而池的容量仍未滿時,就構造一個新的物件,並放入池中,並把物件的狀態設為“佔用”狀態;當需要構造一個物件而池的容量已滿,則從池中選一個“空閒”狀態的物件返回,並把物件的狀態設為“佔用”。當物件使用完後再回收到池中並把狀態設為“空閒“。
這種模式的一個典型應用場景是:
在一個具有很多使用者的web站點裡,需要一個物件來單獨處理一個連線,而每一個連線的時間比較短。如果每次連線都建立一個物件然後又很快銷燬,那麼建立和銷燬物件的系統開銷是很大的。這種時候可以使用物件池,這樣就免去了建立和銷燬物件的開銷。
3。可以方便的丟擲異常。請看下列程式碼:
public class Test {
public Test() {
double x = 1.0/0.0;
}
public static void main(String args[]) {
try {
Test test = new Test();
}catch (Exception e){
System.out.println(e.toString());
}
}
}
編譯,執行,你會發現這個異常不會被捕捉,沒有任何輸出;即使嘗試在建構函式中捕捉異常也不行。看下列程式碼:
public class Test {
public Test() {
try {
System.out.println("trying to throw an exception");
double x = 1.0/0.0;
} catch(Exception e) {
System.out.println("Exception captured");
}finally {
System.out.println("inside finally");
}
}
public static void main(String args[]) {
Test test = new Test();
}
}
編譯,執行,結果為:
trying to throw an exception
inside finally
原因是JVM把建構函式產生的異常丟棄了。試想你正在使用一個第三方的類庫提供的類,那個類提供一個共有的建構函式,它允許你通過引數構造一個類的物件,可是如果你的引數不合法,導致在建構函式中產生一個異常,那麼你永遠不知道具體發生了什麼。當然如可以在每次構造物件時進行引數合法性檢查,可是假設你要構造好多這樣的物件??那將是一場災難。這時可以通過把建構函式的訪問級別設為私有,強迫類的使用者使用一個工廠函式來生成需要的物件,那麼就可以在這個函式中統一的進行引數檢查了。具體的程式碼就不寫了,留給讀者去實踐吧!
從上面的分析我們可以知道私有建構函式的威力。需要注意的一點是,即使你的建構函式什麼都不做,比如:
private Shape() {}
你仍然要顯示的定義,因為如果你不定義,那麼Java會自動為你生成一個空建構函式,而這個空建構函式是共有的。
相關文章
- js之工廠建構函式模式(譯)JS函式模式
- Javascript 之中的 class/建構函式/工廠函式JavaScript函式
- 【譯】JavaScript 工廠函式 vs 建構函式JavaScript函式
- 設計模式-靜態工廠模式設計模式
- 工廠模式的函式模式函式
- c#之saf靜態屬性與建構函式C#函式
- 工廠模式建立物件和自定義建構函式建立物件的異同模式物件函式
- C#靜態建構函式及靜態變數學習C#函式變數
- Yii2設計模式——靜態工廠模式設計模式
- 類中靜態回撥函式應用函式
- C++建構函式和解構函式呼叫虛擬函式時使用靜態聯編C++函式
- 私有建構函式的物件建立例項函式物件
- Rust語言之GoF設計模式:靜態工廠RustGo設計模式
- 設計模式——從介面的角度切入靜態工廠模式設計模式
- 建構函式與解構函式函式
- 應用最廣泛的模式——工廠方法模式模式
- JavaScript進階系列03,通過硬編碼、工廠模式、建構函式建立JavaScript物件JavaScript模式函式物件
- 工廠方法模式與抽象工廠模式的區別模式抽象
- 為什麼要在JAVA工廠模式中使用靜態方法Java模式
- iOS 靜態庫 與私有庫iOS
- 繼承與派生,多繼承,函式過載,建構函式呼叫順序 靜態多型和動態多型繼承函式多型
- [CareerCup] 14.1 Private Constructor 私有構建函式Struct函式
- 關於建構函式與解構函式的分享函式
- 建構函式與普通函式的區別函式
- 抽象工廠模式-與-工廠方法模式區別抽象模式
- 設計模式——簡單工廠(又叫靜態工廠方法,不屬於GOF23中設計模式)設計模式Go
- javascript基礎(this,工廠方法來建立物件,建構函式建立物件)(十六)JavaScript物件函式
- 反射破壞單例的私有建構函式保護反射單例函式
- PHP筆記:建構函式與解構函式PHP筆記函式
- 用抽象工廠方法構建 Flutter 主題抽象Flutter
- IOC與工廠模式模式
- Java 設計模式之工廠方法模式與抽象工廠模式Java設計模式抽象
- 工廠方法、建構函式、原型物件——JS基礎學習筆記(四)函式原型物件JS筆記
- 設計模式 | 簡單工廠模式及典型應用設計模式
- JS 建構函式與類JS函式
- 綜合使用抽象工廠、工廠方法的應用抽象
- 預設建構函式、引數化建構函式、複製建構函式、解構函式函式
- 類的建構函式和解構函式函式