前言
掌握設計模式的層次java
設計模式介紹程序員
設計模式分爲三種類型,共23種數據庫
建立型模式:單例模式,抽象工廠模式,原型模式,建造者模式,工程模式。編程
結構型模式:適配器模式,橋接模式,裝飾模式,組合模式,外觀模式,享元模式,代理模式設計模式
行爲型模式:模塊方法模式,命令模式,訪問者模式,迭代模式,觀察者模式,中介者模式,備忘錄模式,解釋器模式(Interpreter模式),狀態模式,策略模式,職責鏈模式(責任鏈模式)安全
注意:不一樣的書籍上對分類和名稱略有差異。session
單例模式
單例模式介紹多線程
所謂類的單例設計模式,就是採起必定的方法保證再整個的軟件系統中,對某個類只能存在一個對象實例,而且該類只提供了一個取得對象實例的方法(靜態方法)。框架
好比Hibernate的SessionFactory,他充當數據存儲源的代理,並負責建立Session對象。SessionFactory並非輕量級的,通常狀況下,一個項目一般只須要一個SessionFactoury就夠,這是就會用到單例模式。jvm
單例設計模式有八種寫法
餓漢式(靜態常量)
構造器私有化(防止 new)
類的內部建立對象
向外暴露一個靜態的公共方法。gentInstance
代碼實現
public class SingletonTest1 { public static void main(String[] args) { //測試 Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); System.out.println(instance == instance1);//true System.out.println("instance.hashCode=" + instance.hashCode());//1163157884 System.out.println("instance1.hashCode=" + instance1.hashCode());//1163157884 } } //餓漢式(靜態變量) class Singleton { //1. 私有化構造器,外部不能能new private Singleton() {} //2. 在本類內部建立對象實例 private final static Singleton instance = new Singleton(); //3. 提供一個共有的靜態方法,返回實例對象 public static Singleton getInstance() { return instance; } }
優缺點說明
餓漢式(靜態代碼塊)
代碼
public class SingletonTest2 { public static void main(String[] args) { //測試 Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); System.out.println(instance == instance1);//true System.out.println("instance.hashCode=" + instance.hashCode());//1163157884 System.out.println("instance1.hashCode=" + instance1.hashCode());//1163157884 } } //餓漢式(靜態變量) class Singleton { //1. 私有化構造器,外部不能能new private Singleton() { } //2. 在本類內部建立對象實例 private static Singleton instance; //在靜態代碼塊中,建立對象 static { instance = new Singleton(); } //3. 提供一個共有的靜態方法,返回實例對象 public static Singleton getInstance() { return instance; } }
優缺點說明
懶漢式(線程不安全)
代碼
public class SingletonTest03 { public static void main(String[] args) { //測試 System.out.println("懶漢式1,線程不安全"); Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); System.out.println(instance == instance1);//true System.out.println("instance.hashCode=" + instance.hashCode());//1163157884 System.out.println("instance1.hashCode=" + instance1.hashCode());//1163157884 } } class Singleton { private static Singleton instance; public Singleton() { } //提供一個靜態的共有方法,當使用該方法時,纔去建立instance //即懶漢式 public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
懶漢式(線程安全,同步方法)
代碼
class Singleton{ private static Singleton singlenton; private Singleton(){} //加入了同步代碼,解決線程不安全問題 public static synchronized Singlenton getInstance(){ if(singleton==null){ singleton=new Singleton(); } return singleton; } }
優缺點說明
懶漢式(線程安全,同步代碼塊)
代碼
class Singleton{ private static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(singleton==null){ //同代碼塊 synchronized (Singleton.class){ singleton=new Singleton(); } return singleton; } } }
優缺點說明
雙重檢查
代碼演示
class Singleton{ //volatile把它認爲是一個輕量級的synchronized private static volatile Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(singleton==null){ //保證只有一個線程在這裏執行,當下一個線程進來的時候, //上一個線程已經建立完了singleton已經不等於null了,就不會建立了 //提供一個靜態的共有方法,加入雙重檢查代碼,解決線程安全問題,同時解決懶加載問題 //同時保證了效率,推薦使用 synchronized(Singleton.class){ if(singleton==null){ singleton=new Singleton(); } } } return singleton; } }
優缺點說明
靜態內部類
代碼演示
//當外部類裝載的時候靜態內部類不會被裝載的 //當咱們調用靜態方法時靜態內部類的時候只會裝載一次,並且裝載的時候線程是安全的。 public class SingletonTest07 { public static void main(String[] args) { Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); System.out.println(instance == instance1);//true System.out.println("instance.hashCode=" + instance.hashCode());//instance1.hashCode=1163157884 System.out.println("instance1.hashCode=" + instance1.hashCode());//instance1.hashCode=1163157884 } } //靜態內部類完成,推薦使用 class Singleton { //構造器私有化 private Singleton() { } //寫靜態內部類,該類有一個靜態屬性 private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } //提供一個靜態的共有方法,直接返回SingletonInstance.INSTANCE public static Singleton getInstance() { return SingletonInstance.INSTANCE; } }
優缺點說明
枚舉
代碼實例
public class SingletonTest8 { public static void main(String[] args) { Singleton instance = Singleton.INSTANCE; Singleton instance2 = Singleton.INSTANCE; System.out.println(instance == instance2);//true System.out.println(instance.hashCode());//1163157884 System.out.println(instance2.hashCode());//1163157884 instance.sayOK(); } } //使用枚舉能夠實現單例,推薦使用 enum Singleton { INSTANCE; public void sayOK() { System.out.println("ok~");} }
單例模式在jdk應用的源碼分析
單例模式在jdk應用的源碼分析
//單例設計模式的懶漢式 public class Runtime { private static Runtime currentRuntime = new Runtime(); public static Runtime getRuntime() { return currentRuntime; } private Runtime() {}
單例模式注意事項和細節說明