//最近海口出差,但學習還是要堅持。好幾天沒上CSDN了,有點想念。希望有一天,我也能天天敲代碼。。。
//設計模式,不應該是模板,應該是編程思想,學習的本質,不在於記住她,而在於她觸發了你的思想!
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
public class SingleTest {
public static void main(String[] args) throws Exception{
//==================1
SingleDemo sg=SingleDemo.getInstence();
SingleDemo sg1=SingleDemo.getInstence();
System.out.println(sg==sg1);
//==================2
/*SingleDemo01 sg2=SingleDemo01.getInstence();
SingleDemo01 sg21=SingleDemo01.getInstence();
System.out.println(sg2==sg21);*/
//=================3
SingleDemo03 sg3=SingleDemo03.getInstence();
SingleDemo03 sg31=SingleDemo03.getInstence();
System.out.println(sg3==sg31);
//====================
System.out.println(SingleDemo04.INSTENCE==SingleDemo04.INSTENCE);
SingleDemo04.INSTENCE.dowith();
//============通過反射 調用私有構造器
/*Class<SingleDemo01> cla=(Class<SingleDemo01>) Class.forName("mine.singleton.SingleDemo01");
Constructor<SingleDemo01> c=cla.getDeclaredConstructor(null);
c.setAccessible(true);
SingleDemo01 instence=c.newInstance();*/
//=======通過序列化 反序列化 創建多個實例
SingleDemo01 sg2=SingleDemo01.getInstence();
SingleDemo01 sg21=SingleDemo01.getInstence();
System.out.println(sg2);
//=================================
FileOutputStream fos=new FileOutputStream("D:/1.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(sg2);
oos.flush();
oos.close();
fos.close();
//=================================
FileInputStream fis=new FileInputStream(new File("D:/1.txt"));
ObjectInputStream ois=new ObjectInputStream(fis);
SingleDemo01 sss=(SingleDemo01) ois.readObject();
System.out.println(sss);
ois.close();
fis.close();
}
}
/**
* 單例模式:餓漢式
* 線程安全 調用效率高
*
*/
class SingleDemo{
//類加載時 天然的線程安全。立即加載,不延時。可能會浪費資源
private static SingleDemo instence=new SingleDemo();
private SingleDemo(){
}
public static SingleDemo getInstence(){
return instence;
}
}
/**
* 單例模式:懶漢式
* 延時加載 ,真正用的時候才加載。
* 資源利用率高
* 同步方法,併發效率低
*/
class SingleDemo01 implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
//延時加載,真正用的時候 再加載
private static SingleDemo01 instence;
private SingleDemo01(){
if(null!=instence){//防止 反射調用 構造器。寫項目一般不需要這樣考慮
throw new RuntimeException();
}
}
//方法同步,調用效率低
public static synchronized SingleDemo01 getInstence(){
if(instence==null){
instence=new SingleDemo01();
}
return instence;
}
//==========防止反序列化,生成多個實例
public Object readResolve(){
return instence;
}
}
/**
* 單例模式:雙重檢測鎖
* 由於編譯器優化,與jvm底層模型的問題,偶爾會出問題,不建議使用
*/
class SingleDemo02{
private static SingleDemo02 instence;
private SingleDemo02(){}
public static SingleDemo02 getInstence(){
if(instence==null){
SingleDemo02 sg;
synchronized(SingleDemo02.class){
sg=instence;
if(sg==null){
synchronized(SingleDemo02.class){
if(sg==null){
sg=new SingleDemo02();
}
}
return sg;
}
}
}
return instence;
}
}
/**
* 單例模式:靜態內部類
* 兼具:併發高效,延時加載,
* 線程安全
* 外部類 沒有static屬性,所以不會像餓漢式直接加載
*/
class SingleDemo03{
private static class SingleInstence{
//instence是 static final 類型保證了只有這樣一個實例存在,而且只能賦值一次,保證線程安全
private static final SingleDemo03 instence=new SingleDemo03();
}
private SingleDemo03(){
}
public static SingleDemo03 getInstence(){
return SingleInstence.instence;
}
}
/**
* 單例模式:枚舉
* 沒有懶加載
* 避免了 序列化反序列化和反射的漏洞
*/
enum SingleDemo04{
INSTENCE;
//==================
public void dowith(){
System.out.println("我是枚舉類型的單實例");
}
}