單例模式:
定義:
確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例
簡單來說就是這個類只能有一個實例,必須自己創建自己的唯一實例,必須給其它所有對象提供這一實例
適用場景:
在一個系統內,要求一個類有且僅有一個對象
優點:
減少了內存,避免了對資源的多重佔用,對於創建比較繁瑣的對象,只生成一個實例,減少了系統的性能開銷
缺點:
單例模式一般沒有接口,擴展困難
實現:
1).餓漢式單例(立即加載)
public class Danli {
private Danli(){
}
private static Danli danli=new Danli();
public static Danli getInstance(){
return danli;
}
}
單例類通過將構造方法設置爲private避免類在外部被實例化,其他類只能通過getInstance()方法訪問到這個唯一實例
餓漢式單例在類加載初始化時就創建好一個靜態的對象供外部使用,這個對象不會改變,所以本身就是線程安全的
2).懶漢式單例(延遲加載方式)
public class Danli {
private Danli(){
}
private static Danli danli=null;
public static Danli getInstance(){
if(danli==null){
danli=new Danli();
}
return danli;
}
}
該寫法在多線程模式下會產生多個danli對象,應該對在多線程環境下的懶漢式單例就行改進
public class Danli {
private Danli() {
}
private static Danli danli = null;
public static Danli getInstance() {
if (danli == null) {
synchronized (Danli.class) {
if(danli==null) {
danli = new Danli();
}
}
}
return danli;
}
}
在方法上加synchronized同步鎖解決了多線程環境下多個實例對象的問題,但是運行效率低下,下一個線程想要獲取對象,就必須等待上一個線程釋放鎖以後,所以使用雙重檢查進一步優化,可以避免整個方法被鎖,可以提高執行效率
雙重檢查懶加載的問題:在Java指令中創建對象和賦值操作是分開進行的,即danli=new Danli()語句分兩步執行,但JVM不能保證這兩個操作的先後順序,可能JVM會爲新的Danli實例分配空間,然後直接賦值給Instance成員,然後再去初始化這個Danli實例,這樣當其它線程訪問到Danli實例時,因爲沒有初始化就會報錯
針對上邊的問題,可以使用Volatile來禁止重排序,但是在JDK1.5之前Volatile不能解決重排序問題,在此之前可以採取靜態內部類的方法實現
3).靜態內部類實現
public class Danli{
private Danli(){
}
//靜態內部類
private static class Inner{
private static Danli danli=new Danli();
}
public static Danli getInstance(){
return Inner.danli;
}
}
靜態內部類雖然保證了單例模式在多線程下的線程安全,但是在遇到序列化對象時,默認的方式運行得到的結果就是多例的
4).static靜態代碼塊實現
public class Danli{
private Danli(){
}
private static Danli danli=null;
//靜態代碼塊
static{
danli=new Danli();
}
public static Danli getInstance(){
return danli;
}
}
5).內部枚舉類實現
public class SingletonFactory {
// 內部枚舉類
private enum EnmuSingleton{
Singleton;
private Singleton8 singleton;
//枚舉類的構造方法在類加載是被實例化
private EnmuSingleton(){
singleton = new Singleton8();
}
public Singleton8 getInstance(){
return singleton;
}
}
public static Singleton8 getInstance() {
return EnmuSingleton.Singleton.getInstance();
}
}
class Singleton8{
public Singleton8(){}
}
工廠方法模式:
定義:
定義一個用於創建對象的接口,讓子類決定實例化哪一個類,工廠方法將一個類的實例化延遲到子類
適用場景:
有大量產品需要創建,並且具有共同的接口時,可以通過工廠方法模式進行創建
簡單工廠模式:
抽象工廠方法:
裝飾模式:
定義:
動態的給一個對象添加一些新的功能,要求裝飾對象和被裝飾對象實現同一個接口,裝飾對象持有被裝飾對象的實例
簡單理解就是,這裏有有3個類,人類,男人類,女人類,人類是父類,男人類和女人類是子類,如果使用繼承這裏就多了2個類,但是用裝飾模式,可以直接將人類裝飾城男人類或者女人類,不用進行繼承,降低了類與類之間的耦合
適用場景:
需要擴展一個類的功能,需要動態的給一個對象增加一個功能,這些功能可以再動態撤銷
缺點:
產生過多相似的對象,不容易排查錯誤
觀察者模式:
定義:
定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴它的對象都會得到通知並自動更新
適用場景:
需要遍歷集合中的對象
外觀模式: