1. 程式人生 > >淺談常見設計模式--單例模式 簡單工廠模式

淺談常見設計模式--單例模式 簡單工廠模式

今題那站在這裡和大家一起分享最近在一本書上看到的關於設計模式的內容,接下來要講的設計模式有:

  1. 單例模式
  2. 簡單工廠模式
  3. 工廠方法和抽象工廠
  4. 代理模式
  5. 命令模式
  6. 策略模式
  7. 門面模式
  8. 橋接模式
  9. 觀察者模式

接下來詳細介紹滅一種設計模式(注意:下面的講解都是基於java語言)

1.單例模式

定義:Java中單例模式定義:“一個類有且僅有一個例項,並且自行例項化向整個系統提供。”

java單例模式程式碼片段:

public class SingletonClass{
    private static volatile SingletonClass instance=null;
    public static SingletonClass getInstance(){
        if(instance==null){
            synchronized(SingletonClass.class){
                if(instance==null){
                    instance=new SingletonClass();
                }
            }
        }
        return instance;
    }
    private SingletonClass(){}
}

為什麼需要單例模式?

  1. 對於系統中的某些類來說,只有一個例項很重要,例如,一個系統中可以存在多個列印任務,但是隻能有一個正在工作的任務;一個系統只能有一個視窗管理器或檔案系統;一個系統只能有一個計時工具或ID(序號)生成器。如在Windows中就只能開啟一個工作管理員。如果不使用機制對視窗物件進行唯一化,將彈出多個視窗,如果這些視窗顯示的內容完全一致,則是重複物件,浪費記憶體資源;如果這些視窗顯示的內容不一致,則意味著在某一瞬間系統有多個狀態,與實際不符,也會給使用者帶來誤解,不知道哪一個才是真實的狀態。因此有時確保系統中某個物件的唯一性即一個類只能有一個例項非常重要
  2. 如何保證一個類只有一個例項並且這個例項易於被訪問呢?定義一個全域性變數可以確保物件隨時都可以被訪問,但不能防止我們例項化多個物件。一個更好的解決辦法是讓類自身負責儲存它的唯一例項。這個類可以保證沒有其他例項被建立,並且它可以提供一個訪問該例項的方法。這就是單例模式的模式動機

單例模式的要點

  1. 顯然單例模式的要點有三個;一是某個類只能有一個例項;二是它必須自行建立這個例項;三是它必須自行向整個系統提供這個例項。

設計單例模式通常有三種形式:

第一種:懶漢模式(常用的)

public class SingletonClass{
    private static SingletonClass instance=null;
    public static synchronized SingletonClass getInstance()
    {
        if(instance==null)
        {
               instance=new SingletonClass();
        }
        return instance;
    }
    private SingletonClass(){
    }
}

第二種:餓漢式

//對第一行static的一些解釋
// java允許我們在一個類裡面定義靜態類。比如內部類(nested class)。
//把nested class封閉起來的類叫外部類。
//在java中,我們不能用static修飾頂級類(top level class)。
//只有內部類可以為static。
public class Singleton{
    //在自己內部定義自己的一個例項,只供內部呼叫
    private static final Singleton instance = new Singleton();
    private Singleton(){
        //do something
    }
    //這裡提供了一個供外部訪問本class的靜態方法,可以直接訪問
    public static Singleton getInstance(){
        return instance;
    }
}

第三種:

public class Singleton{
    private static Singleton instance=null;
    private Singleton(){
        //do something
    }
    public static synchronized Singleton getInstance(){
        if(instance==null){
            synchronized(Singleton.class){
                if(instance==null) {  
                      instance=new Singleton();
                }
            }
        }
        return instance;
    }
}內容下方到if內部,提高了執行的效率,不必每次獲取物件時都進行同步,只有第一次才同步,建立了以後就沒必要了



2.簡單工廠模式

為什麼會有簡單工廠模式?

  • 對於java應用而言,應用之中各例項之間存在複雜的呼叫關係。當A物件需要呼叫B物件的方法時,許多人會選擇new一個B物件例項,然後通過B物件例項呼叫相應的方法。這種做法的壞處在於:A類的方法實現直接呼叫了B類的類名(這種方式也被稱為硬編碼耦合),一旦系統需要重構:需啊喲使用C類來代替B類的時候,程式不得不更改A類程式碼。
  • 為了解決需要重寫A類程式碼的問題,我們需要重新定義一個工廠類BFactory,專門用來建立B物件例項,而A類只需要呼叫BFactory工廠的方法來得到B物件例項

簡單工廠模式深入分析:

  • 簡單工廠模式解決的問題是如何去例項化一個合適的物件。
  • 簡單工廠模式的核心思想就是:有一個專門的類來負責建立例項的過程。
  • 具體來說,把產品看著是一系列的類的集合,這些類是由某個抽象類或者介面派生出來的一個物件樹。而工廠類用來產生一個合適的物件來滿足客戶的要求。
  • 如果簡單工廠模式所涉及到的具體產品之間沒有共同的邏輯,那麼我們就可以使用介面來扮演抽象產品的角色;如果具體產品之間有功能的邏輯或,我們就必須把這些共同的東西提取出來,放在一個抽象類中,然後讓具體產品繼承抽象類。為實現更好複用的目的,共同的東西總是應該抽象出來的。

在實際的的使用中,抽閒產品和具體產品之間往往是多層次的產品結構,如下圖所示:

這裡寫圖片描述

簡單工廠模式使用場景分析及程式碼實現:
GG請自己的女朋友和眾多美女吃飯,但是GG自己是不會做飯的或者做的飯很不好,這說明GG不用自己去建立各種食物的物件;各個美女都有各自的愛好,到麥當勞後她們喜歡吃什麼直接去點就行了,麥當勞就是生產各種食物的工廠,這時候GG不用自己動手,也可以請這麼多美女吃飯,所要做的就是買單O(∩_∩)O哈哈~,其UML圖如下所示:
這裡寫圖片描述

產品的抽象介面

/*
 1. 產品的抽象介面
 */
public interface Food {
    /*
     * 獲得相應的食物
     */
    public void get();
}

麥香雞對抽象產品介面的實現

/*
 2. 麥香雞對抽象產品介面的實現
 */
public class McChicken implements Food{
    /*
     * 獲取一份麥香雞
     */
    public void get(){
        System.out.println("我要一份麥香雞");
    }
}

薯條對抽象產品介面的實現

/*
 3. 薯條對抽象產品介面的實現
 */
public class Chips implements Food{
    /*
     * 獲取一份薯條
     */
    public void get(){
        System.out.println("我要一份薯條");
    }
}

現在建立一個食物加工工廠:

public class FoodFactory {
 
    public static Food getFood(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        if(type.equalsIgnoreCase("mcchicken")) {
            return McChicken.class.newInstance();
 
        } else if(type.equalsIgnoreCase("chips")) {
            return Chips.class.newInstance();
        } else {
            System.out.println("哎呀!找不到相應的例項化類啦!");
            return null;
        }
 
 
    }
}

簡單工廠模式的優缺點分析:

  1. 優點:
  • 工廠類是整個模式的關鍵所在。它包含必要的判斷邏輯,能夠根據外界給定的資訊,決定究竟應該建立哪個具體類的物件。使用者在使用時可以直接根據工廠類去建立所需的例項,而無需瞭解這些物件是如何建立以及如何組織的。有利於整個軟體體系結構的優化。

缺點:

  • 由於工廠類集中了所有例項的建立邏輯,這就直接導致一旦這個工廠出了問題,所有的客戶端都會受到牽連;而且由於簡單工廠模式的產品室基於一個共同的抽象類或者介面,這樣一來,但產品的種類增加的時候,即有不同的產品介面或者抽象類的時候,工廠類就需要判斷何時建立何種種類的產品,這就和建立何種種類產品的產品相互混淆在了一起,違背了單一職責,導致系統喪失靈活性和可維護性。而且更重要的是,簡單工廠模式違背了“開放封閉原則”,就是違背了“系統對擴充套件開放,對修改關閉”的原則,因為當我新增加一個產品的時候必須修改工廠類,相應的工廠類就需要重新編譯一遍。

**總結一下:**簡單工廠模式分離產品的建立者和消費者,有利於軟體系統結構的優化;但是由於一切邏輯都集中在一個工廠類中,導致了沒有很高的內聚性,同時也違背了“開放封閉原則”。另外,簡單工廠模式的方法一般都是靜態的,而靜態工廠方法是無法讓子類繼承的,因此,簡單工廠模式無法形成基於基類的繼承樹結構。