設(shè)計(jì)模式:設(shè)計(jì)模式是在大量的實(shí)踐中總結(jié)和理論化后優(yōu)選的代碼結(jié)構(gòu)、編程風(fēng)格、以及解決問(wèn)題的思考方式。
一共有23種設(shè)計(jì)模式。
單例的設(shè)計(jì)模式:
1、解決的問(wèn)題:使得一個(gè)類(lèi)只能夠創(chuàng)建一個(gè)對(duì)象。
2、如何實(shí)現(xiàn)?見(jiàn)如下四步
//餓漢式1
public class TestSingleton {
public static void main(String[] args) {
? ? ? Singleton s1 = Singleton.getInstance();
? ? ? Singleton s2 = Singleton.getInstance();
? ? ? System.out.println(s1 == s2);//true,說(shuō)明這兩個(gè)引用的地址是一樣的
}
}
//只能創(chuàng)建Singleton的單個(gè)實(shí)例
class Singleton{
//1、私有化構(gòu)造器,使得在類(lèi)的外部不能夠調(diào)用此構(gòu)造器
private Singleton(){
}
//2、在類(lèi)的內(nèi)部創(chuàng)建一個(gè)類(lèi)的實(shí)例
//3、私有化此對(duì)象,通過(guò)公共的方法來(lái)調(diào)用
private static Singleton instance = new Singleton();
//4、此公共的方法,只能通過(guò)類(lèi)來(lái)調(diào)用,因?yàn)樵O(shè)置為static的,同時(shí)類(lèi)的實(shí)例也必須為static聲明的
public static Singleton getInstance(){
return instance;
}
}
//餓漢式2
... ? ...
//2、在類(lèi)的內(nèi)部創(chuàng)建一個(gè)類(lèi)的實(shí)例,與1的區(qū)別是是通過(guò)代碼塊實(shí)例化類(lèi)的。
private static Singleton instance = null;
static {
instance = new Singleton();
}
//懶漢式:可能存在線程安全問(wèn)題
public class TestSingleton1 {
public static void main(String[] args) {
Singleton1 s1 = Singleton1.getInstance();
Singleton1 s2 = Singleton1.getInstance();
System.out.println(s1 == s2);//true
}
}
class Singleton1{
//1.
private Singleton1(){
}
//2.
private static Singleton1 instance = null;
//3.
public static Singleton1 getInstance(){
if (instance == null){
instance = new Singleton1();
}
return instance;
}
}
為什么懶漢式可能存在線程安全問(wèn)題?
因?yàn)榧偃缬卸鄠€(gè)執(zhí)行路徑在調(diào)用getinstance()方法,當(dāng)?shù)谝粋€(gè)執(zhí)行路徑由于首次執(zhí)行g(shù)etinstance方法,instance==null,進(jìn)入if循環(huán),但是由于當(dāng)前執(zhí)行的路徑比較多,進(jìn)行了CPU切換,該進(jìn)程被掛起。另外一個(gè)執(zhí)行路徑開(kāi)始執(zhí)行,此時(shí)依舊instance==null,然后創(chuàng)建了instance對(duì)象(0x1111),返回instance;然后切換到第一個(gè)執(zhí)行路徑繼續(xù)執(zhí)行,便接著new一個(gè)新的對(duì)象(0x2222);但是這兩個(gè)引用本身應(yīng)該指向同一個(gè)對(duì)象,此時(shí)便出現(xiàn)線程問(wèn)題。