設計模式(一):單例模式 java實現
阿新 • • 發佈:2019-01-10
參考:http://blog.csdn.net/jason0539/article/details/23297037/
單例模式:指的是一個類只有一個例項物件。它的設計是為了實現類的單一功能。專注於自己的事情。
有如下三個特點:
- 單例類只有一個例項
- 單例類必須自己建立這一個例項
- 單例類必須將自己的這個例項提供給其他物件
因此我們在實現單例類的時候要注意一下幾點:
- 首先禁止他人建立例項物件,故它的建構函式必須是私有的;
- 其次自己建立例項要在類載入時建立,故必須有一個靜態的例項物件的成員變數;
- 要給他人提供例項,故要有一個獲取該方法的公有成員方法。
常見的單例模式的實現有5中方法
- 懶漢式:需要時建立例項,執行緒不安全
- 餓漢式:類載入時就建立,執行緒不安全
- 使用同步方法的懶漢式
- 使用雙重檢查加鎖的懶漢式
- 使用靜態內部類的懶漢式(這個比較推薦)
下面將一一實現:
一、懶漢式
public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance = null;
//測試方法
public void sayHello(String name){
System.out.println("Hello, " + name);
}
/**
* 執行緒不安全的寫法
* @return
*/
public static Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
測試:
public class TestSingleton1 {
public static void main(String[] args){
Singleton1 ins = Singleton1.getInstance();
ins.sayHello("Mike" );
Singleton1 ins2 = Singleton1.getInstance();
ins2.sayHello("Mike");
if(ins == ins2){
System.out.println("同一個例項");
}else{
System.out.println("不同的例項");
}
}
二、餓漢式
public class Singleton2 {
private Singleton2(){
}
private static Singleton2 instance = new Singleton2();
private static Singleton2 getInstance(){
return instance;
}
}
三、懶漢式+同步機制
public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance = null;
//測試方法
public void sayHello(String name){
System.out.println("Hello, " + name);
}
public static synchronized Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
四、懶漢式+雙重檢查鎖定
public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance = null;
//測試方法
public void sayHello(String name){
System.out.println("Hello, " + name);
}
public static Singleton1 getInstance(){
if(instance == null){
synchronized(Singleton1.class){
if(instance == null){
instance = new Singleton1();
}
}
}
return instance;
}
}
五、懶漢式+靜態內部類
public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance = null;
//測試方法
public void sayHello(String name){
System.out.println("Hello, " + name);
}
private static class LazyHolder{
private static final Singleton1 INSTANCE = new Singleton1();
}
public static Singleton1 getInstance(){
return LazyHolder.INSTANCE;
}
}
六、登記式單例類
package designpattern.singleton;
import java.util.HashMap;
import java.util.Map;
/**
* 登記式單例模式
* @author wenbaoli
*
*/
public class Singleton3 {
private static Map<String, Singleton3> map = new HashMap<String, Singleton3>();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保護的預設構造子
protected Singleton3(){}
//靜態工廠方法,返回此類唯一的例項
public static Singleton3 getInstance(String name){
if(name == null){
name = Singleton3.class.getName();
System.out.println("name == null" + "---> name = " + name);
}
if(map.get(name) == null){
try{
map.put(name, (Singleton3) Class.forName(name).newInstance());
}catch(InstantiationException e){
e.printStackTrace();
}catch(IllegalAccessException e){
e.printStackTrace();
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
return map.get(name);
}
//一個示意性的商業方法
public String about(){
return "Hello, I am RegSingleton.";
}
public static void main(String[] args){
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}
測試:
public class TestSingleton3 {
public static void main(String[] args){
Singleton3 single1 = Singleton3.getInstance(null);
System.out.println(single1.about());
System.out.println("------------我是分割線----------");
Singleton3 single2 = Singleton3.getInstance(single1.getClass().getName());
System.out.println(single1.about());
if(single1 == single2){
System.out.println("他們是同一個例項");
}else{
System.out.println("他們是不同的例項");
}
}
}
附錄:查漏補缺——程式碼中我不熟悉或不知道的事
name = Singleton3.class.getName();
: 表示獲取Singleton3這個類的名字。一個類的name是它所在的包名.類名(Singleton3) Class.forName(name).newInstance()
: 表示去載入name(包名.類名)的下的這個類。。。
例如:給你一個字串變數,它代表一個類的包名和類名,你怎麼例項化它?只有你提到的這個方法了,不過要再加一點。 A a = (A)Class.forName(“pacage.A”).newInstance(); 這和你 A a = new A(); 是一樣的效果。