文章出處

單例模式,個人理解就是,使用了這個模式,可以保證一個類只生成唯一的實例對象。就是在整個程序中,這個類只存在一個實例對象。

GoF對單例模式的定義:保證一個類,只有一個實例存在,同時提供能對該實例加以訪問的全局訪問方法。

客戶端的代碼用來測試,獲取到的實例只有一個。直接上代碼。

 1 public class MainClass {
 2     public static void main(String[] args) {
 3         Person person1=Person.getPerson();//獲取Person對象
 4         Person person2=Person.getPerson();//獲取Person對象
 5         person1.setName("Tom");
 6         person2.setName("WhiteTaken");//如果兩個獲取的到的對象的實例,是同一實例,那么打印出來的名字應該是一樣的。
 7         System.out.println(person1.getName());
 8         System.out.println(person2.getName());
 9     }
10 }

如果不是單例模式,而僅僅是創建了幾個對象 ,那么兩次打印的結果,將會是兩個不同的名字。

而單例模式的情況,獲取的到的是同一個對象,那么兩次打印的結果,將是第二次賦值的結果。

單例測試結果如下。

好,上面是測試結果,那么單例模式是怎么實現的呢。

我學習到的三種單例模式的創建方法。

1.直接用final方式創建。只要類執行,就會創建這樣一個對象。

代碼如下。

 1 public class Person {
 2     private String name;
 3     public static final Person perSon= new Person();//注意此處的final
 4     public String getName() {
 5         return name;
 6     }
 7 
 8     public void setName(String name) {
 9         this.name = name;
10     }
11     //構造函數私有化
12     private Person(){
13         
14     }
15     //獲取對象的方法,final實現
16     public static Person getPerson(){
17         return perSon;
18     }
19 }

通過final關鍵字,保證perSon只被賦值一次,即值生成一次對象。

2.第二種方式,通過在獲取對象的方法中判斷person是否為null,如果不存在,則實例化person,如果存在,則直接返回person實例。

 1 public class Person2 {
 2     private String name;
 3     private static Person2 perSon;
 4     public String getName() {
 5         return name;
 6     }
 7     public void setName(String name) {
 8         this.name = name;
 9     }
10     //構造函數私有化
11     private Person2(){
12         
13     }
14     //獲取對象的方法,單線程模式可用
15     public static Person2 getPerson(){
16         if(perSon==null){
17             return perSon=new Person2();
18         }
19         return perSon;
20     }
21 }

以上方法是實現單例模式的第二種方法,但是此種方法有一個天然的劣勢,就是只適合單線程開發。

多線程的話,如果兩個線程同時訪問這個方法的話,返回的person對象可能會出現不一樣的情況 ,那就不是單例了。

如果使用同步方法的話(synchronized),多線程的情況下會造成線程等待,影響效率。

3.第三種方式是通過雙重檢查的方式實現單例。

雙重判斷,通過兩次判斷null,能夠確保在多線程下,只生成一個單例。

 1 public class Person4 {
 2     private String name;
 3     private static Person4 perSon;
 4     public String getName() {
 5         return name;
 6     }
 7 
 8     public void setName(String name) {
 9         this.name = name;
10     }
11     //構造函數私有化
12     private Person4(){
13         
14     }
15     //獲取對象的方法,雙重檢查
16     public static  Person4 getPerson(){
17         if(perSon==null){
18             synchronized (Person4.class) {
19                 if(perSon==null){
20                     return perSon=new Person4();
21                 }                
22             }
23         }
24         return perSon;
25     }
26 }

這樣就完成單例模式的簡單應用。

 

 

 

要想達到學以致用,真的很難,工作久了,很多東西都忘了。。。單例模式寫的一個小例子,加強理解。

需要注意:只創建了一次對象。

 1  class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Console.WriteLine("================測試單例模式=========begin======");
 6             Test tst = GetAllTest.GetTest();
 7             tst.TestPrint();
 8             Test tst2 = GetAllTest.GetTest();
 9             tst2.TestPrint();
10             Console.WriteLine("================測試單例模式=========end========");
11             Console.Read();
12         }
13     }
14 
15 
16     class Test
17     {
18         public Test(){}
19         public void TestPrint()
20         {
21             Console.WriteLine("單例模式打印結果");
22         }
23     }
24 
25     class GetAllTest
26     {
27         private static Test ts;
28         public static Test GetTest()
29         {
30             if(ts == null)
31             {
32                 Console.WriteLine("創建Test對象過程");
33                 ts = new Test();
34             }
35 
36             return ts;
37         }
38     }

打印結果:

好好努力,提高自己!!!


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()