1. 程式人生 > >GOF23設計模式之單例模式

GOF23設計模式之單例模式

直接 exceptio tps tar tput 共享 close implement put

GOF23設計模式(Group Of Four)

為國外很有名的四個大牛總結的23總常見的套路

分類:

1)創建型模式

單例模式、工廠模式、抽象工廠模式、建造者模式、原型模式

2)結構型模式

適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式

3)行為型模式

模板方法模式、命令模式、叠代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式、狀態模式、策略模式、職責鏈模式、訪問者模式

單例模式

核心作用:保證一個類只有一個實例,並且提供一個訪問該實例的全局訪問點

單例模式的優點:

由於單例模式只生成一個實例,減少了系統性能開銷。

單例模式可以在系統設置全局的訪問點,優化共享資源訪問。例如可以設計一個單例類,負責所有數據表的映射處理。

常見的五種單例模式的實現方式:

主要:

餓漢式(線程安全,調用效率高。但是,不能延時加載。)

package cn.taosir.design.create.singleton;

/**
 * 餓漢式
 * @author taosir
 *
 */
public class HungryType {

    //類初始化時立即加載(不具備延時加載的優勢),由於加載類時天然是線程安全的
    private static HungryType hungryType=new HungryType();
    
    //構造方法私有化
    private
HungryType() {}; //開放方法供外部提取實例,方法不需要同步,調用效率高 public static HungryType getInstance() { return hungryType; } }

懶漢式(線程安全,調用效率不高。但是,可以延時加載。)

package cn.taosir.design.create.singleton;
/**
 * 懶漢式
 * @author taosir
 *
 */
public class LazyType {
    
    //類初始化時,不初始化這個對象(延時加載,真正需要的時候才創建實例)
private static LazyType lazyType; //構造方法私有化 private LazyType() {}; //方法同步,調用效率低 public static synchronized LazyType getInstance() { if(lazyType==null) lazyType=new LazyType(); return lazyType; } }

其他:

雙重檢測鎖式(由於JVM底層內部模型原因,偶爾會出現問題,不建議使用)

靜態內部類式(線程安全,調用效率高。但是,可以延時加載,結合了餓漢式和懶漢式的優點)

package cn.taosir.design.create.singleton;
/**
 * 靜態內部類實現
 * @author taosir
 *
 */
public class StaticInner {

    //使用一個靜態的內部類來創建實例,當使用下面的StaticInnerInstance.staticInner時才會初始化
    private static class StaticInnerInstance{
        private static final StaticInner staticInner=new StaticInner();
    }
    
    //方法沒有同步,調用效率高
    public static StaticInner getInstance() {
        return StaticInnerInstance.staticInner;
    }
    
    //私有化構造方法
    private StaticInner() {}
}

枚舉單例(線程安全、調用效率高,不能延時加載)

package cn.taosir.design.create.singleton;
/**
 * 枚舉單例
 * @author taosir
 *
 */
public enum Enumeration {

    //這個枚舉元素本身就是單例
    INSTANCE;
    
    //添加自己需要的操作
    public void doYouWantToDo() {
        
    }
}

使用反射和反序列化破解單利模式及如何防止破解

破解單例模式的方法

package cn.taosir.design.create.singleton;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;

/** 
 * * 測試反射和反序列化破解單利模式
 * @author Administrator
 *
 */
public class CrackDemo {
    public static void main(String[] args) throws Exception {
        
        
        LazyType4Crack lazy=LazyType4Crack.getInstance();
        
        //反射
//        Class<LazyType4Crack> clazz=(Class<LazyType4Crack>)Class.forName("cn.taosir.design.create.singleton.LazyType4Crack");
//        Constructor<LazyType4Crack> constructor=clazz.getDeclaredConstructor(null);
//        constructor.setAccessible(true);//此方法可以跳過權限的檢查,破解單例
//        LazyType4Crack lazyOne=constructor.newInstance();
//        System.out.println(lazy);
//        System.out.println(lazyOne);
//        System.out.println(lazy==lazyOne);
        
        //序列化
        FileOutputStream fos=new FileOutputStream("./a.txt");
        ObjectOutputStream ooStream=new ObjectOutputStream(fos);
        ooStream.writeObject(lazy);
        ooStream.close();
        fos.close();
        //反序列化
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("./a.txt"));
        LazyType4Crack layCrack=(LazyType4Crack)ois.readObject();
        System.out.println(lazy==layCrack);
    }
}
 

防止破解的方法(以懶漢式為例)

package cn.taosir.design.create.singleton;

import java.io.Serializable;

/**
 * * 懶漢式(如何防止反射和反序列化漏洞)
 * @author taosir
 *
 */
public class LazyType4Crack implements Serializable{

    //類初始化時,不初始化這個對象(延時加載,真正需要的時候才創建實例)
    private static LazyType4Crack lazyType4Crack;

    //構造方法私有化
    private LazyType4Crack() {
     //防止反射
if(lazyType4Crack!=null) { throw new RuntimeException(); } } //方法同步,調用效率低 public static synchronized LazyType4Crack getInstance() { if(lazyType4Crack==null) lazyType4Crack=new LazyType4Crack(); return lazyType4Crack; } //反序列化時,如果定義了readResolve()則直接返回此方法指定的對象。而不需要單獨再創建新對象 private Object readResolve() { return lazyType4Crack; } }

GOF23設計模式之單例模式