前幾天校園招聘會,投簡歷時就直接給我來了一份筆試題。我一看,臥槽,全都是考很基本很基本的題,可以說基本到噁心,然而對於我這個實習了半年,可以獨自把一個項目完成的程序猿來說,很可惜這些基本題卻把我放倒了,真是諷刺啊。就感覺一個全棧工程師被問如何輸出一個helloworld被嚇得跪地直喊OMG一樣,哈哈,開個玩笑。沒辦法,面向學生招聘,企業都愛玩這一套,對於我這個有實戰經驗的人來說,儘管這些基本的東西感覺在實際項目還真不怎麼用得上,但還是得去沉澱一下啊。
筆試題的組成基本少不了數據結構和設計模式,既然你把我放倒了,那麼我就從設計模式開始補回來吧,堅持一天一種模式學習吧。
首先是設計模式裏最簡單的一種模式,單例模式。顧名思義,就是一個類,在使用的時候確保只有一個實例被初始化。
第一步,創建一個單例類:
SingleTon.java
public class SingleTon {
private static SingleTon instance;
private int count;
//構造方法爲私有,無法直接new()獲得實例
private SingleTon(){
count=0;
}
public static SingleTon getInstance(){
if(instance==null){
instance=new SingleTon();
}
return instance;
}
public void print(){
System.out.println(count);
}
public void add(){
System.out.println("變量加1");
count++;
}
}
第二步,創建一個運行測試類:
PatternTest.java
public class PatternTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
SingleTon singleTon1=SingleTon.getInstance();
singleTon1.print();
singleTon1.add();
SingleTon singleTon2=SingleTon.getInstance();
singleTon2.print();
}
}
運行結果:
果然很簡單吧,兩次獲取實例都是同一個實例,所以加一操作add()也只是在同一個對象上的成員變量加一。
不過,對於單例模式,若是比較起其性能,如內存,線程安全等,則有幾種不同的實現方式。
1. 節省內存(懶漢模式),非線程安全式:
public class SingleTon {
private static SingleTon instance;
//構造方法爲私有,無法直接new()獲得實例
private SingleTon(){}
public static SingleTon getInstance(){
if(instance==null){
instance=new SingleTon();
}
return instance;
}
}
實際上就和上面一開始的代碼一樣,只有使用時才實例化,但沒有考慮到線程安全。
2. 節省內存, 線程安全,效率慢式:
public class SingleTon {
private static SingleTon instance;
//構造方法爲私有,無法直接new()獲得實例
private SingleTon(){}
public static synchronized SingleTon getInstance(){
if(instance==null){
instance=new SingleTon();
}
return instance;
}
}
就是在getInstance()方法里加個同步鎖而已,雖然可以達到線程安全,但效率慢。
3. 耗內存,線程安全,效率快式:
public class SingleTon {
private static SingleTon instance=new SingleTon();
//構造方法爲私有,無法直接new()獲得實例
private SingleTon(){}
public static SingleTon getInstance(){
return instance;
}
}
就直接在加載類的時候就初始化了,這樣會耗內存,但不使用synchronize鎖,這樣就可以不用加同步鎖也可以達到線程安全的效果。
實際上還有其他的方式,但一般都是使用第三種方式創建單例多。