設計模式(四):單例模式與工廠模式

来源:http://www.cnblogs.com/lovesong/archive/2016/06/10/5573521.html
-Advertisement-
Play Games

在未讀《JavaScript設計模式》這本書前,在我的印象里,單例模式就是每個類只會產生一個實例,非常簡單。在細看到這個模式時候,有些疑惑單例模式與工廠模式的區別,雖然看起來像最大區別在於是否多次實例化。 單例(Singleton)模式 單例模式它限制了類的實例化次數只能一次。在實例不存在的情況下, ...


在未讀《JavaScript設計模式》這本書前,在我的印象里,單例模式就是每個類只會產生一個實例,非常簡單。在細看到這個模式時候,有些疑惑單例模式與工廠模式的區別,雖然看起來像最大區別在於是否多次實例化。

單例(Singleton)模式

單例模式它限制了類的實例化次數只能一次。在實例不存在的情況下,可以通過一個方法創建一個類來實現創建類的新實例;如果實例已經存在,它會簡單返回該對象的引用。(這跟我想的一樣)

例子:

var mySingleton = (function () {
  // Instance stores a reference to the Singleton
  var instance;
  function init() {
    // Singleton
    // Private methods and variables
    function privateMethod(){
        console.log( "I am private" );
    }
    var privateVariable = "Im also private";
    var privateRandomNumber = Math.random();
    return {
      // Public methods and variables
      publicMethod: function () {
        console.log( "The public can see me!" );
      },
      publicProperty: "I am also public",
      getRandomNumber: function() {
        return privateRandomNumber;
      }
    };
  };
  return {
    // Get the Singleton instance if one exists
    // or create one if it doesn't
    getInstance: function () {
      if ( !instance ) {
        instance = init();
      }
      return instance;
    }
  };
})();

特別地方:

1. 單例不同於靜態類(或對象),因為我們可以推遲它們的初始化(通常是因為它們需要的參數信息在類定義時是無法獲得的),直到需要使用靜態實例時,無需使用資源或記憶體。

2. 單例的唯一實例能夠通過子類去擴展,使用者不用更改代碼就能使用一個擴展的實例。

3. 單例將導致測試變困難,不利於單元測試。

何時使用單例(When it really is a singleton):

一個類是否是一個單例,必須確定下麵三點:

1. Will every application use this class exactly the same way? (exactly is the key word)

2. Will every application ever need only one instance of this class? (ever and one are the key words)

3. Should the clients of this class be unaware of the application they are part of?

PS:這三點是由文章http://www.ibm.com/developerworks/webservices/library/co-single/index.html提出。

我的理解是:

1. 是否每個應用程式使用這個類的方式都完全相同?

2. 是否每個應用程式任何時候都只需要一個類的實例?

3. 使用者不需要知道該類是這應用程式的哪個部分?(或許翻譯不好)

當滿足這三個點,那就可以用單例。關鍵就在於類的使用方式都相同,並且不需要應用上下文。

工廠(Factory)模式

工廠模式提供一個通用的介面來創建對象。

例子:

function Car( options ) {
  this.doors = options.doors || 4;
  this.state = options.state || "brand new";
  this.color = options.color || "silver";
}
 
function Truck( options){
  this.state = options.state || "used";
  this.wheelSize = options.wheelSize || "large";
  this.color = options.color || "blue";
}
 
function VehicleFactory() {}
VehicleFactory.prototype.createVehicle = function ( options ) {
  switch(options.vehicleType){
    case "car":
      this.vehicleClass = Car;
      break;
    case "truck":
      this.vehicleClass = Truck;
      break;
    //defaults to VehicleFactory.prototype.vehicleClass (Car)
  }
  return new this.vehicleClass( options );
};
var carFactory = new VehicleFactory();
var car = carFactory.createVehicle( {
            vehicleType: "car",
            color: "yellow",
            doors: 6 } );
console.log( car instanceof Car ); // Outputs: true

何時使用工廠:

1. 當對象或組件設置非常複雜的時候。

2. 當需要根據所在的不同環境輕鬆生成對象的不同實例時。

3. 當處理很多共用相同屬性的小型對象或組件時。

4. 對象的實例只需要滿足一個約定——鴨子類型(duck typing)。利於解耦。

PS:鴨子類型——“當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。”我們並不關心對象是什麼類型,到底是不是鴨子,只關心行為。

抽象工廠(Abstract Factory)模式

書中描述:

使用抽象工廠模式場景:一個系統必須獨立於它所創建的對象的生成方式,或它需要與多種對象類型一起工作。

PS:我覺得沒描述清楚。

網上定義:

為創建一組相關或相互依賴的對象提供一個介面,而且無需指定他們的具體類。

PS:這個才比較清晰。

我的理解:

在工廠模式的加上一層抽象,工廠的工廠。

 

總結

單例模式和工廠模式概念上是比較簡單,但是在使用上需要留心。該不該用單例,就考慮上面講的單例三要點;該不該用工廠,就要看它是否帶來大量不必要的複雜性,帶來不必要的開銷(不為了用模式而用模式)。抽象工廠模式並沒有找到好的示例,就先略下。

另外越讀這本書,越覺得在某些譯文上有些問題,太過於直譯,我覺得應該要結合理解做翻譯,不然就像外國人講普通話,太怪了。

 

參考文獻

1. 《Learning JavaScript Design Patterns》 by Addy Osmani

https://addyosmani.com/resources/essentialjsdesignpatterns/book/

2. 《JavaScript設計模式》by 徐濤【譯】

 

本文為原創文章,轉載請保留原出處,方便溯源,如有錯誤地方,謝謝指正。

本文地址 :http://www.cnblogs.com/lovesong/p/5573521.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • J2SE 1.5提供了另一種形式的for迴圈。藉助這種形式的for迴圈,可以用更簡單地方式來遍曆數組和Collection等類型的對象。本文介紹使用這種迴圈的具體方式,說明如何自行定義能被這樣遍歷的類,並解釋和這一機制的一些常見問題。 在Java程式中,要“逐一處理”――或者說,“遍歷”――某一個數 ...
  • 本文是我閱讀周志明老師《深入理解Java虛擬機-JVM高級特性與最佳實戰》章節2.2的學習筆記。更多內容,請參考原書。 Java虛擬機在執行Java程式時會將其所管理的記憶體劃分為若幹個不同的數據區域,這些區域有各自的用途及生命周期。具體而言包括以下幾個區域。 1. 程式計數器 一塊較小的記憶體空間,可 ...
  • 原文地址:http://blog.csdn.net/cq361106306/article/details/38736551 synchronized--同步 顧名思義是用於同步互斥的作用的。 這裡精簡的記一下它的使用方法以及意義: 當synchronized修飾this或者非靜態方法或者是一個實例... ...
  • synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。 1. synchronized 方法:通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。如:public synchronized void ...
  • △abstract不可以修飾成員變數 △一個類可以沒有抽象方法,可以定義為抽象類,這樣的目的是不能讓其他類建立本類對象,交給子類完成. △abstract和static(可以被類名調用方法,但是抽象方法調用沒有意義)final(不能被覆蓋方法)private(私有方法無法覆蓋) △介面只能被實現.被 ...
  • 首先介紹一款簡單利落的分頁利器:bootstrap-paginator 效果截圖: GitHub官方下載地址:https://github.com/lyonlai/bootstrap-paginator 備用下載地址:http://files.cnblogs.com/files/Dreamer-1/ ...
  • 在《JavaScript設計模式》關於中介者模式的介紹里,裡面有些錯誤和擅自添加的例子,雖然例子(英文版沒有)是為了讓人更好理解,但是該篇章加上的例子卻給人誤導的感覺,所以如果有人讀這個章節時,建議看英文版。 在看這個模式時候,我只想弄明白一點,中介者模式與訂閱/發佈模式的區別在哪? 中介者模式定義 ...
  • 1.意圖 運用共用技術有效地支持大量細粒度的對象。 2.動機 Flyweight模式描述瞭如何共用對象,使得可以細粒度地使用它們,而無需高昂的代價。flyweight是一個共用對象,它可以同時在多個場景(context)中使用,並且在每個場景中flyweight都可以作為一個獨立的對象 這一點與非共 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...