工廠模式+單例模式


工廠的三種模式:目的都是解耦

簡單工廠

工廠是一個類:生產各種各樣產品;不同類實現接口;業務全部在fractory中,違反了開閉原則。

 使用在業務簡單的情況下。

工廠方法(如果工廠的產品全部屬於同一個等級結構,則屬於工廠方法。)

定義一個創建對象的工廠接口,讓子類決定實例化哪一個類,將實際工作交給子類

例子:

工廠是一個接口,produceTrunk()  ,實現創建不同卡車類

卡車也是一個接口,實現不同卡車類

將不同卡車的業務邏輯抽離出fractory

優點

符合開閉原則,每增加一種產品,只需要增加相應具體的產品類和工廠子類。

符合單一職責原則,每個具體工廠類只負責創建對應的產品。

缺點

在增加一個新產品時,需要增加一個產品類和一個具體的子工廠,每個工廠生產一種產品,太過單一。

 

抽象工廠(如果工廠的產品來自多個等級結構,則屬於抽象工廠模式)

抽象工廠角色:具體工廠必須時間的接口。

具體工廠角色:和具體業務邏輯相關的代碼,創建對應的具體產品的對象。

抽象工廠:producetrunk();  producesedan();

具體工廠:寶馬工廠(寶馬轎車、寶馬卡車)奧迪工廠(奧迪轎車、奧迪卡車)

抽象產品:卡車、轎車

具體產品:寶馬卡車,寶馬轎車,奧迪卡車,奧迪轎車

單例模式

概念:包含一個被稱為單例的特殊類。

特點:單例類只能有一個實例;單例類必須自己創建自己的唯一實例;單例類必須給所有其他對象提供這一實例。

實現:private 構造類避免了外部類對此類進行實例化

場景需求

1.計數器,不用每次刷新都在數據庫里加一次,用單例先緩存起來。

2.創建的一個對象需要消耗的資源過多,比如IO與數據庫的連接等。

如何選擇:

餓漢式是線程安全的,但是類加載就創建對象。如果在一個工廠模式下,緩存了很多實例,就得考慮效率問題,因為這個類一加載就把所有實例一起創建了(不管用不用);懶漢式優點是延時加載,缺點是需要用同步。看實際需求選擇。

優點:在內存中只有一個實例,減少了內存開銷,尤其是頻繁創建和銷毀實例(工具類);避免對資源的多重占用(比如寫文件操作)

缺點:擴展很困難(private修飾的方法無法繼承,不能再擴展)

餓漢式單例

在類加載初始化時就創建好一個靜態的對象供外部使用,除非系統重啟,這個對象不會改變,本身是線程安全的。

package single;
public class singlethon {
    //構造方法私有化
    singlethon() {}
    private static singlethon single=new singlethon();
    //對外提供調用
    public static singlethon getinstance() {
        return single;
    }
}

懶漢式單例

類加載的時候不創建對象,只有在使用的時候才創建,但是在多線程條件下,是線程不安全的。

package single;

import javax.sql.rowset.spi.SyncFactory;

public class single2 {
    private single2() {}
    private static single2 single=null;
    //同步鎖,一個線程執行時,其他線程處於等待
    synchronized public static single2 getinstance() {
        if(single==null) {
            //線程不安全
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            single=new single2();
        }
        return single;
    }
}
//多線程,CPU 交替執行有先后

可以用同步鎖解決線程不安全問題,但是加鎖會降低效率;為提高效率,減小代碼同步范圍。但是用了雙重檢索,也不一定是線程安全的,因為還有系統指令重拍,此時可以將對象用volatile修飾。

package single;

import javax.sql.rowset.spi.SyncFactory;

public class single2 {
    private single2() {}
    private static single2 single=null;
    //同步鎖,一個線程執行時,其他線程處於等待
     public static single2 getinstance() {
        //雙重檢索
             if(single==null) {
                    //線程不安全
                 synchronized(single2.class) {
                     if(single==null) {
                         single=new single2();
                     }
                } 
             }
        return single;
    }
}
//多線程,CPU 交替執行有先后

靜態內部類

package single;
public class single3 {
    private single3() {}
    //外部類被加載,內部類沒有被加載,除非主動使用
    private static class insideclass {
        private static single3 single=new single3();
    }
    
    public static single3 getinstance() {
        return insideclass.single;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM