1. 程式人生 > >Java中靜態成員類及靜態內部類的Builder模式構建物件、靜態內部類構建單例模式

Java中靜態成員類及靜態內部類的Builder模式構建物件、靜態內部類構建單例模式

一、什麼是巢狀類

巢狀類是指被定義在另一個類的內部的類。巢狀類存在的目的應該只是為他的外圍類提供服務。如果巢狀類將來可能會用於其他的某個環境中,它就應該是頂層類。巢狀類有四種:靜態成員類、非靜態成員類、匿名類和區域性類。除了第一種之外,其他三種被稱為內部類。

二、什麼是靜態內部類
  • 靜態成員類是最簡單的一種巢狀類。最好把他看做是普通類,只是碰巧被宣告在另一個類的內部而已,它可以訪問外圍類的所有成員,包括哪些被宣告為私有的成員。靜態成員類是外圍類的一個靜態成員,與其他的靜態成員一樣,也遵守同樣的可訪問規則。如果他被宣告為私有的,他就只能在外圍類的內部才可以被訪問,等等。
  • 靜態內部類可以有多個例項,跟普通的類一樣,所以在多執行緒環境下要注意這一點。
三、靜態內部類的用法
  • 靜態成員類的一種常見的用法是作為公有的輔助類,僅當與它的外部類一起使用時才有意義。例如考慮一下列舉,他描述了計算器支援的各種操作。
public class Calaculator {

    public enum Operation{
        ADD,DIVE,PLUS,MUL;
    }

    public static void main(String[] args) {
        System.out.println(Calaculator.Operation.ADD);
    }
}
  • 從語法上講,靜態成員類和非靜態成員類之間唯一的區別是,靜態成員類的宣告中包含修飾符static。儘管他們的語法非常相似,但是這兩種巢狀類有很大的不同。非靜態成員類的每個例項都隱含著與外圍類的一個外圍例項相關聯。在非靜態成員類的例項方法內部,可以呼叫外圍例項的方法,或者利用修飾過的this構造獲得外圍例項的引用。如果巢狀類的例項可以在它外圍類的例項之外獨立存在,這個巢狀類必須是靜態成員類:在沒有外圍例項的情況下,想要建立非靜態成員類的例項是不可能的。
四、 靜態內部類Builder模式建立物件
  • 靜態工廠和建構函式都可以建立一個類的物件,它們有一個共同的侷限性就是引數過多時可讀性不是很好,如果有很多的可選引數的話也不是很好控制,他也有自己的有點,使用靜態工廠模式或建構函式模式是一種相對安全的模式;
  • JavaBean的模式,這樣就解決類靜態工廠或者建構函式中遇到的引數過多可讀性不好及可選引數控制的問題。
  • Builder模式,這種模式即相容了靜態工廠或者建構函式的安全性,也保證了像JavaBean那樣的可讀性,也可以說是一種相對完美的解決方法。
    如下是一個使用靜態內部類的Builder模式構建的示例:
package ggindex.v2.stock.model;

import
java.util.Date; import java.util.Map; public class Symbol { //指標名稱 private String index_name; //開始日期 private Date start_date; //結束日期 private Date end_date; //分類ID private Integer class_id; public Symbol(Builder builder) { this.index_name = builder.index_name; this.start_date = builder.start_date; this.end_date = builder.end_date; this.class_id = builder.class_id; } public String getIndex_name() { return index_name; } public void setIndex_name(String index_name) { this.index_name = index_name; } public Date getStart_date() { return start_date; } public void setStart_date(Date start_date) { this.start_date = start_date; } public Date getEnd_date() { return end_date; } public void setEnd_date(Date end_date) { this.end_date = end_date; } public Integer getClass_id() { return class_id; } public void setClass_id(Integer class_id) { this.class_id = class_id; } public static class Builder{ //指標名稱 private String index_name; //開始日期 private Date start_date; //結束日期 private Date end_date; //分類ID private Integer class_id; public Builder setIndexName(String indexName) { this.index_name = indexName; return this; } public Builder setStartDate(Date startDate) { this.start_date = startDate; return this; } public Builder setEndDate(Date endDate) { this.end_date = endDate; return this; } public Builder setClassId(Integer classId) { this.class_id = classId; return this; } public Symbol build() { return new Symbol(this); } } }

構建Symbol例項物件:

public class Test {

    public static void main(String[] args) {
        Symbol symbol = new Symbol.Builder().setClassId(1)
                            .setEndDate(new Date())
                            .setStartDate(new Date())
                            .setIndexName("test")
                            .build();
    }
}
五、靜態內部類實現執行緒安全的單例模式

平時實現單例模式的時候通常會使用懶漢模式、餓漢模式;懶漢模式要實現執行緒安全的單例模式,如下程式碼:

public class Singleton {    

  //單例例項變數    
  private static Singleton instance = null;    

  //私有化的構造方法,保證外部的類不能通過構造器來例項化    
  private Singleton() {}    

  //獲取單例物件例項    
  public static Singleton getInstance() {    
      if (instance == null) {     
          synchronized (Singleton.class) {        
              Singleton temp = instance;     
              if (temp == null) {    
                  synchronized (Singleton.class) {    
                      temp = new Singleton();         
                  }    
                  instance = temp;                   
              }    
          }    
      }    
      return instance;    
  }       
} 

我們可以看到,要實現一個執行緒安全的單例類外面包了一層一層的鎖synchronized,讓人感覺很繁瑣。

我們看一下餓漢模式實現執行緒安全的單例模式:

public class Singleton {    

  //單例變數 ,static的,在類載入時進行初始化一次,保證執行緒安全     
  private static Singleton instance = new Singleton();        

  //私有化的構造方法,保證外部的類不能通過構造器來例項化。         
  private Singleton() {}    

  //獲取單例物件例項         
  public static Singleton getInstance() {    
      return instance;    
  }    
}

這樣可以簡單的實現執行緒安全的單例類,但是也會存在一個問題,這種模式只要類已初始化就會例項化單例類,如果載入的資源很多,而且一直也不用的話就會造成資源的浪費。

看下面的靜態內部類,可以很好的解決上面存在的問題,節省資源、程式碼簡潔、執行緒安全性:

package ggindex.v2.stock.model;

//內部類實現懶漢模式
public class Singleton {

    public static class SingletonHolder{
        private static Singleton singleton = new Singleton();
    }
    //私有的建構函式,使外部類無法通過 構造器構造例項
    private Singleton() {}
    //獲取單例物件
    public static Singleton getInstance() {
        return SingletonHolder.singleton;
    }
}