爲國外頗有名的四個大牛總結的23總常見的套路html
單例模式、工廠模式、抽象工廠模式、建造者模式、原型模式java
適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式設計模式
模板方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式、狀態模式、策略模式、職責鏈模式、訪問者模式安全
核心做用:保證一個類只有一個實例,而且提供一個訪問該實例的全局訪問點性能
因爲單例模式只生成一個實例,減小了系統性能開銷。測試
單例模式能夠在系統設置全局的訪問點,優化共享資源訪問。例如能夠設計一個單例類,負責全部數據表的映射處理。優化
餓漢式(線程安全,調用效率高。可是,不能延時加載。)spa
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; } }