1. 程式人生 > >Java設計模式理論知識即單例設計模式

Java設計模式理論知識即單例設計模式

程式:1.可維護性、2.可複用性、3.可擴充套件性、4.靈活性好 ;通過封裝、繼承、多型把程式的耦合度降低 開放-封閉原則(設計總原則) 開閉原則就是說對擴充套件開放,對修改關閉。在程式需要進行拓展的時候,不能去修改原有的程式碼,而是要擴充套件原有程式碼,實現一個熱插拔的效果。所以一句話概括就是:為了使程式的擴充套件性好,易於維護和升級。想要達到這樣的效果,我們需要使用介面和抽象類等 單一職責原則 就一個類而言,應該僅有一個引起它變化的原因(如果你能夠想到多於一個的動機去改變一個類,那麼這個類就具有多一個的職責,就應該考慮類的職責分離) 依賴倒轉原則 抽象不應該依賴細節,細節應該依賴於抽象;高層模組不應該依賴低層模組。兩個都應該依賴抽象 里氏代換原則

子型別必須能夠替換它們的父型別。 只有當子類可以替換掉父類,在軟體單位的功能不受到影響時,父類才能真正被複用,而子類也能夠在父類的基礎上增加新的行為。正是因為子類的可替換性才使得使用父類型別的模組在無需修改的情況下就可以擴充套件。 如果編寫時考慮的都是如何針對抽象程式設計而不是針對細節程式設計,即程式中所有的依賴關係都是終止於抽象類或者介面,那就是面向物件的射擊,反之那就是過程化的設計。 迪米特原則 如果兩個類不必彼此直接通訊,那麼這兩個類就不應當發生直接的相互作用,如果其中一個類需要呼叫另一個類的某一個方法的話,可以通過第三者轉發這個呼叫。 合成/聚合複用原則 如果新物件的某些功能在別的已經建立好的物件裡面已經實現,那麼儘量使用別的物件提供的功能,使之成為新物件的一部分,而不要自己再重新建立。新物件通過向這些物件的委派達到複用已有功能的。 簡而言之,要儘量使用合成/聚合,儘量不要使用繼承。 介面隔離原則
不需要將所有的東西都放在一個接口裡面,應該是定義多個功能專一的介面。過於臃腫的介面只會強迫客戶依賴於不需要的方法。 設計模式的分類 總體來說設計模式分為三大類: 建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。 結構型模式,共七種:介面卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。 行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式。

單例模式(singleton)—單執行緒

保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點,避免一個全域性使用的類頻繁的建立和銷燬,節省系統資源,提高程式效率。Java是這麼建立例項的 Person p = new Person();但是這麼建立會建立多個例項,所以我們必須把構造器(構造方法)設為私有(private),這樣其他類就不能使用new來例項化一個類。所有類都有構造方法,不編碼則系統預設生成空的構造方法,若有顯示定義的構造方法,則預設的構造方法就會失效。 “通常我們可以讓一個全域性變數使得一個物件被訪問,但他不能防止你例項化多個物件。一個最好的辦法就是,讓類自身負責儲存它的唯一例項。這個可以保證沒有其它例項可以被建立,並且它可以提供一個訪問該例項的方法。” 在這裡插入圖片描述

Singleton 類,定義一個GetInstance 操作,允許客戶訪問它的唯一例項。GetInstance 是一個靜態方法,主要負責建立自己的唯一例項。

package singleton;

public class Singleton {
    //定義一個屬性,用來儲存Singleton類物件的例項
    private static Singleton instance;

    //構造方法讓其private,這樣就可以堵死外界利用new建立此類例項的可能
    private Singleton() {
    }

    //此方法是獲得本類例項的唯一全域性訪問點
    public static Singleton GetInstance() {
        //若例項不存在,則new一個新例項,否則返回已有的例項
        if (instance == null) {
            instance = new Singleton();
        }
        return instance; //若例項存在,直接返回例項物件
    }
}

客戶端程式碼

package singleton;

import java.io.Console;

public class Main {

    public static void main(String[] args) {
        Singleton s1 = Singleton.GetInstance();
        Singleton s2 = Singleton.GetInstance();
        //比較兩次例項化後物件的結果是例項相同
        System.out.println(s1 == s2);  //結果為true---->表示為同一個例項物件
    }
}

這種實現方式並不是執行緒安全的,當有多個執行緒同時呼叫Singleton.getInstance()方法時會產生多個例項。需要通過改造,在多線下如何實現單例模式。可以給程序一把鎖來處理,確保當一個執行緒位於程式碼的臨界區時,另一個執行緒不進入臨界區。如果其他執行緒檢視進入鎖定的程式碼,則它將一直等待(即被阻止),直到該物件被釋放。

package singleton;

public class Singleton {
    //定義一個屬性,用來儲存Singleton類物件的例項
    private static Singleton instance;

    //構造方法讓其private,這樣就可以堵死外界利用new建立此類例項的可能
    private Singleton() {
    }

    //此方法是獲得本類例項的唯一全域性訪問點
    public static Singleton GetInstance() {
        //先判斷實力是否存在,不存在再加鎖處理
        //synchronized加鎖同步會降低效率,這裡先判斷是否為空
        //不為空則不需要加鎖,提高程式效率
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance; //若例項存在,直接返回例項物件
    }
}

現在這樣,我們不用讓執行緒每次都加鎖,而只是在例項未被建立的時候再加鎖處理。同時也能保證多執行緒的安全。這種做法被稱為雙重鎖定。

package cn.smbms.tools;

public class Singleton {
   
   private static Singleton singleton;
   
   private Singleton(){
      //在整個應用執行期間,只執行一次的業務程式碼操作(比如:讀取配置檔案的操作)
   }
   
   public static class SingletonHelper{
      private static final Singleton INSTANCE = new Singleton();
   }
   
   public static Singleton getInstance(){
      return SingletonHelper.INSTANCE;
   }
   public static Singleton test(){
      return singleton;
   }
}

客戶端程式碼

package cn.smbms.tools;

public class TestSingleton {
   public static void main(String[] args) {
      System.out.println("Singleton.test()-----> " 
            + Singleton.test());
      
      System.out.println("Singleton.getInstance()-----> " 
                  + Singleton.getInstance());
   }
}

測試結果 在這裡插入圖片描述 在靜態初始化的方式是在自己被載入時就將自己例項化,所以被形象的稱之為餓漢式單例類(缺點是,會提前佔用系統資源)。而在第一次被引用時,才會將自己例項化,被稱之為懶漢式單例類(缺點是,面臨多執行緒訪問的安全性問題,及非執行緒安全模式類)。 單例模式優點 1 在記憶體中只有一個物件,節省記憶體空間。 2 避免頻繁的建立銷燬物件,可以提高效能。 3 避免對共享資源的多重佔用。 4 可以全域性訪問。 適用場景 1 需要頻繁例項化然後銷燬的物件。 2 建立物件時耗時過多或者耗資源過多,但又經常用到的物件。 3 有狀態的工具類物件。 4 頻繁訪問資料庫或檔案的物件。 5 以及其他所有要求只有一個物件的場景。