[設計模式]單例設計模式

weixin_34292959發表於2014-11-10

1:單例模式(面試)

單例模式:單一的例項.保證類在記憶體中只有一個物件.
舉例:

①windows的列印費服務.網站的計數器.(如果一個網站統計訪問量有多個計數器,就會有問題.)
②Java中的應用:資料庫連線池,Runtime這個類.

2.如何保證類在記憶體中只有一個物件?

A:把構造方法私有,為了不讓外界建立物件.
B:在類中建立 一個物件.(有一個物件,還是要建立它)
C:通過一個公共的訪問方式,給外界一個入口.(否則外界根本就無法訪問到)

 

3.餓漢式單例模式:

Student.java

 1 public class Student {
 2     //為了不讓外界訪問,我們把構造方法私有.
 3     private Student(){
 4         
 5     }
 6     //建立一個物件
 7     //為了滿足靜態方法訪問,這裡也必須加一個靜態修飾符static(暫時先不加private,慢慢引入private)
 8     //static Student s = new Student();
 9     private static Student s = new Student();
10     
11     //提供一個公共的訪問方式
12     //(訪問這個方法可以通過Student類的物件,但是構造方法私有化了無法讓外界訪問)
13     //所以為了讓外界直接訪問,只能讓這個方法靜態.
14     public static Student getStudent(){
15         //比如說我有t1和t2同時來訪問,那麼這個時候.拿的都是上面new的
17         return s;
18         //如果此時上面的Student s = new Student();不用靜態修飾,報錯.內容如下
19         //Cannot make a static reference to the non-static field s
20         //一個靜態的上下文,不能有一個非靜態的變數.
21         //所以為了滿足靜態方法訪問,new Student的時候必須用static修飾.
22     }
23     
24     public void show(){
25         System.out.println("我愛java");
26     }
27 }

測試類:StudentTest.java

 1 public class StudentTest {
 2     public static void main(String[] args) {
 3         /*
 4         Student s1 = new Student();
 5         Student s2 = new Student();
 6         System.out.println(s1 == s2);//false
 7         */
 9         //由於成員變數是被靜態static修飾的,前面沒有加訪問修飾符,預設是default外界也可以通過類名訪問的.
10         //Student.s = null;
11         //這樣的話下面執行s1.show()的時候就會報java.lang.NullPointerException
12         //為了不讓外界訪問s,就再在new 的時用private修飾. 這樣此時
13                     
14         //通過單例模式獲取物件並呼叫方法.
15         
16         Student s1 = Student.getStudent();
17         Student s2 = Student.getStudent();
18         System.out.println(s1 == s2);//true
19         
20         s1.show();
21         s2.show();
22     }
23 }

4:懶漢式單例模式(想用的時候再用)

懶漢式有一個非常重要的思想----延遲載入思想.
我們什麼時候需要,你就什麼時候給. 這個思想在Hibernate和Spring中都用了這個思想.  特別是Hibernate框架中的lazy....

Teacher.java

 1 public class Teacher {
 2     // 為了不讓外界建立物件,把構造方法私有.
 3     private Teacher() {
 4     }
 5 
 6     // 本類建立一個物件.
 7     // 加static是為了保證靜態方法可以訪問.
 8     // 加private是為了保證外界不能直接訪問
 9     private static Teacher t = null;
10 
11     // 提供公共的訪問方式.
12     //synchronized是為了解決懶漢式多執行緒不安全加上的.
13     //被同步的程式碼,在某一時刻只能被一個執行緒訪問.
14     public synchronized static Teacher getTeacher() {
15                 /*
16                 比如說我有t1和t2同時來訪問,那麼這個時候.
17                 當t1進來後,判斷這個時候t是null
18                 所以,t1就進去執行if所控制的語句.
19                 但是注意了,由於執行緒的隨機性.可能當t1剛進去要執行if說控制的語句.
20                 發現,這個時候t還是null,所以,t2也去執行if所控制的語句了.
21                 那麼將來就會有多個物件被建立.
22                 */
23         // 當外界需要使用它,就在這裡new一個.
24         if (t == null) {
25             // 只有第一次訪問這裡的時候才進入if語句new一個物件.
26             // 第二次的時候因為第一次已經new了一個Teacher,並且Teacher是用static修飾
27             // static修飾的是共享的.有值了,就不再進入if了.
28             t = new Teacher();
29         }
30         return t;
31     }
32 
33     // 寫了一個方法
34     public void love() {
35         System.out.println("老師愛學生");
36     }
37 }

TeacherTest.java

 1 public class TeacherTest {
 2     public static void main(String[] args) {
 3         Teacher t1 = Teacher.getTeacher();
 4         Teacher t2 = Teacher.getTeacher();
 5         System.out.println(t1 == t2);// true
 6 
 7         t1.love();
 8         t2.love();
 9     }
10 }

5:那麼我們在開發中到底使用誰呢?

一般開發中使用第一種方案(餓漢式)
原因是:
前提:多執行緒安全問題.
面試的時候會面試懶漢式. 並且,請注意,面試懶漢式,主要是面試下面幾個問題:
A:延遲載入思想.
B:執行緒安全問題.
a:執行緒安全問題是怎麼產生的.
b:執行緒安全問題是怎麼解決的.

6:其實在JDK中提供的類中,已經有單例模式的應用.是誰呢?Runtime類.

附上JDK中關於Runtime類的原始碼:

Runtime.java

 1 public class Runtime {
 2     //這就是一個餓漢式的應用.
 3     private static Runtime currentRuntime = new Runtime();
 4     
 5     public static Runtime getRuntime() { 
 6         return currentRuntime;
 7     }
 8     
 9     private Runtime() {}        
10         
11 }    

 

相關文章