一、什麼是單例模式
單例模式是一種對象創建型模式,使用單例模式,可以保證爲一個類只生成唯一的實例對象。也就是說,在整個程序空間中,該類只存在一個實例對象。
其實,GoF對單例模式的定義是:保證一個類、只有一個實例存在,同時提供能對該實例加以訪問的全局訪問方法。
二、爲什麼要使用單例模式呢?
在應用系統開發中,我們常常有以下需求:
- 在多個線程之間,比如servlet環境,共享同一個資源或者操作同一個對象
- 在整個程序空間使用全局變量,共享資源
- 大規模系統中,爲了性能的考慮,需要節省對象的創建時間等等。
因爲Singleton模式可以保證爲一個類只生成唯一的實例
對象,所以這些情況,Singleton模式就派上用場了。
三、單例模式實現
1.餓漢式:
package com.qianyan.singleton;
public class Person {
private static final Person person = new Person();
private String name;
//構造方法私有化
private Person(){
}
//創建一個全局可訪問的靜態方法
public static Person getInstance(){
return person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.懶漢式(非線程安全,在多線程下有問題):
package com.qianyan.singleton;
public class Person1 {
private static Person1 person;
private String name;
//私有化構造方法
private Person1(){
}
//創建一個全局可訪問的靜態方法
public static Person1 getInstance(){
if(person == null)
return new Person1();
return person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
線程安全(效率低):
package com.qianyan.singleton;
public class Person2 {
private static Person2 person;
private String name;
//私有化構造方法
private Person2(){
}
//創建一個全局可訪問的靜態方法,使用同步方法
public static synchronized Person2 getInstance(){
if(person == null)
person = new Person2();
return person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.雙重檢查:
package com.qianyan.singleton;
public class Person3 {
private static Person3 person;
private String name;
//私有化構造方法
private Person3(){
}
//創建一個全局可訪問的靜態方法,使用同步方法
public static Person3 getInstance(){
if(person == null)
synchronized(Person3.class){
if(person == null)
person = new Person3();
}
return person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
測試類:
package com.qianyan.singleton;
public class MainClass {
public static void main(String[] args) {
/*Person p1 = Person.getInstance();
p1.setName("zhangsan");
Person p2 = Person.getInstance();
p2.setName("lisi");
System.out.println(p1.getName());
System.out.println(p2.getName());*/
/*Person1 p1 = Person1.getInstance();
p1.setName("zhangsan");
Person1 p2 = Person1.getInstance();
p2.setName("lisi");
System.out.println(p1.getName());
System.out.println(p2.getName());*/
/*Person2 p1 = Person2.getInstance();
Person2 p2 = Person2.getInstance();
p1.setName("zhangsan");
p2.setName("lisi");
System.out.println(p1);
System.out.println(p2);*/
Person3 p1 = Person3.getInstance();
Person3 p2 = Person3.getInstance();
p1.setName("zhangsan");
p2.setName("lisi");
System.out.println(p1.getName());
System.out.println(p2.getName());
}
}