1. 程式人生 > >設計模式之常用的設計模式

設計模式之常用的設計模式

什麼是設計模式?
設計模式(Design pattern)代表了最佳的實踐,通常被有經驗的面向物件的軟體開發人員所採用。設計模式是軟體開發人員在軟體開發過程中面臨的一般問題的解決方案。這些解決方案是眾多軟體開發人員經過相當長的一段時間的試驗和錯誤總結出來的。通俗的說:設計模式是前輩、大牛在實際程式設計中對遇到的問題解決方案的抽象。
設計模式的分類
總體來說設計模式分為三大類:
建立型模式,共五種:工廠模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共七種:介面卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式。
在這裡我們重點的說一下常用的一些設計模式。
單例模式


在我們開發中會經常用到單例模式,例如建立目錄、資料庫連線的單執行緒操作;某個需要被頻繁訪問的例項物件;Android網路框架的實現類等。
單例模式保證一個類只有一個例項存在,並提供一個可以訪問它的全域性訪問點。這樣做的好處就是減少記憶體開銷,同時也可以避免對資源的多重佔用。
單例模式有多重寫法,下面我們就列舉下最常用的幾種:
1.餓漢模式

public class Singleton {
    /**
     * 餓漢模式
     */
    private static Singleton instance = new Singleton();
    private Singleton
(){ } public static Singleton getInstance() { return instance; } }

這種方式是在類載入過程中就完成初始化操作,會影響類的載入速度,但是獲取物件的速度快。
2.懶漢模式(非執行緒安全)

public class Singleton {
    /**
     * 懶漢模式(非執行緒安全)
     */
    private static Singleton instance;
    private Singleton (){
    }
    public static Singleton getInstance
() { if (instance == null) { instance = new Singleton(); } return instance; } }

懶漢模式申明一個靜態物件,在使用者第一次呼叫getInstance()時初始化物件,雖然節約資源,但第一次載入時需要例項化,會影響載入速度,而且在多執行緒不能正常工作。
3.懶漢模式(執行緒安全)

    /**
     * 懶漢模式(執行緒安全)
     */
    private static Singleton instance;
    private Singleton (){
    }
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    }

這種模式可以很好的在多執行緒中工作,但是每次呼叫getInstance()都需要進行同步,而且日常開發中基本上不會用到同步。因此不推薦這種寫法。
4.雙重檢查模式 (DCL)

    /**
     * 雙重檢查模式
     */
    private volatile static Singleton instance;
    private Singleton (){
    }
    public static Singleton getInstance() {
        if (instance== null) {
            synchronized (Singleton.class) {
                if (instance== null) {
                    instance= new Singleton();
                }
            }
        }
        return instance;
    }
    }

這種方式在getInstance()方法中對instance進行了兩次判空,第一次是為了不必要的同步,第二次是在instance等於null的情況下才建立例項。DCL優點是資源利用率高,第一次執行getInstance()時單例物件才被例項化,效率高。缺點是第一次載入時反應稍慢一些,在高併發環境下也有一定的缺陷,雖然發生的概率很小。DCL雖然在一定程度解決了資源的消耗和多餘的同步,執行緒安全等問題,但是他還是在某些情況會出現失效的問題,也就是DCL失效,在《java併發程式設計實踐》一書建議用靜態內部類單例模式來替代DCL。
5.靜態內部類單例模式

    /**
     * 靜態內部類單例模式
     */
    private Singleton(){
    }
    public static Singleton getInstance(){
        return SingletonHolder.sInstance;
    }
    private static class SingletonHolder {
        private static final Singleton sInstance = new Singleton();
    }
    }

第一次載入Singleton類時並不會初始化sInstance,只有第一次呼叫getInstance方法時虛擬機器載入SingletonHolder 並初始化sInstance ,這樣不僅能確保執行緒安全也能保證Singleton類的唯一性,推薦使用靜態內部類單例模式。
6.使用容器實現單例模式

public class SingletonManager {
  
    private static Map<String, Object> objMap = new HashMap<>();
  

    private SingletonManager() {
  }
  

    public static void registerService(String key, Object instance) {
    if (!objMap.containsKey(key)) {
      objMap.put(key, instance);
    }
  }
  

    public static Object getService(String key) {
    return objMap.get(key);
  }
}

用SingletonManager 將多種的單例類統一管理,在使用時根據key獲取物件對應型別的物件。這種方式使得我們可以管理多種型別的單例,並且在使用時可以通過統一的介面進行獲取操作,降低了使用者的使用成本,也對使用者隱藏了具體實現,降低了耦合度。

未完待續……