菜鳥之路-淺談設計模式之單例設計模式

單例設計模式

定義:確保一個類僅僅有一個實例,并且自行實例化并向整個系統提供這個實例。



單例模式是一種經常使用的軟件設計模式。在它的核心結構中僅僅包括一個被稱為單例的特殊類。

通過單例模式能夠保證系統中一個類僅僅有一個實例并且該實例易于外界訪問,從而方便對實例個數的控制并節約系統資源。假設希望在系統中某個類的對象僅僅能存在一個,單例模式是最好的解決方式。



關于單例設計模式的動機

對于系統中的某些類來說。僅僅有一個實例非常重要,比如。一個系統中能夠存在多個打印任務,可是僅僅能有一個正在工作的任務;一個系統僅僅能有一個窗體管理器或文件系統;一個系統僅僅能有一個計時工具或ID(序號)生成器。如在Windows中就僅僅能打開一個任務管理器。

假設不使用機制對窗體對象進行唯一化,將彈出多個窗體。假設這些窗體顯示的內容全然一致,則是反復對象。浪費內存資源;假設這些窗體顯示的內容不一致。則意味著在某一瞬間系統有多個狀態,與實際不符。也會給用戶帶來誤解,不知道哪一個才是真實的狀態。

因此有時確保系統中某個對象的唯一性即一個類僅僅能有一個實例非常重要。
怎樣保證一個類僅僅有一個實例而且這個實例易于被訪問呢?定義一個全局變量能夠確保對象隨時都能夠被訪問。但不能防止我們實例化多個對象。

一個更好的解決的方法是讓類自身負責保存它的唯一實例。這個類能夠保證沒有其它實例被創建。而且它能夠提供一個訪問該實例的方法。

這就是單例模式的模式動機


關于單例設計模式的要點

單例模式的要點有三個。一是某個類僅僅能有一個實例。二是它必須自行創建這個實例;三是它必須自行向整個系統提供這個實例。
從詳細實現角度來說,就是下面三點:一是單例模式的類僅僅提供私有的構造函數,二是類定義中含有一個該類的靜態私有對象,三是該類提供了一個靜態的公有的函數用于創建或獲取它本身的靜態私有對象。

Java實例:

當一個類的實例能夠有且僅僅能夠一個的時候就須要用到了。為什么僅僅須要有一個呢?有人說是為了節約內存。但這僅僅是單例模式帶來的一個優點。僅僅有一個實例確實降低內存占用。但是我覺得這不是使用單例模式的理由。

我覺得使用單例模式的時機是當實例存在多個會引起程序邏輯錯誤的時候。比方類似有序的號碼生成器這種東西。怎么能夠同意一個應用上存在多個呢?



餓漢式單例

public class Singleton {  private static Singleton singleton = new Singleton();  private Singleton(){}  public static Singleton getInstance(){  return singleton;  }  
}

懶漢式單例

public class Singleton {  private static Singleton singleton;  private Singleton(){}  public static synchronized Singleton getInstance(){  if(singleton==null){  singleton = new Singleton();  }  return singleton;  }  
} 
可是這樣的單例類型在多線程中是不安全。有可能會出現兩個INSTANCE,為什么呢?
假設當唯一實例尚未創建時,有兩個線程同一時候調用創建方法,那么它們同一時候沒有檢測到唯一實例的存在,從而同一時候各自創建了一個實例,這樣就有兩個實例被構造出來,從而違反了單例模式中實例唯一的原則。 解決問題的辦法是為指示類是否已經實例化的變量提供一個相互排斥鎖(詳見雙重鎖單例。盡管這樣會減少效率)。

比較:
餓漢式是線程安全的,在類創建的同一時候就已經創建好一個靜態的對象供系統使用,以后不在改變。
懶漢式適合單線程。多線程情況下假設在創建實例對象時不加上synchronized則會導致對對象的訪問不是線程安全的。
從實現方式來講他們最大的差別就是懶漢式是延時載入,?
他是在須要的時候才創建對象,而餓漢式在載入類時創建實例。?
?餓漢式無需關注多線程問題、寫法簡單明了、能用則用。可是它是載入類時創建實例、所以假設是一個工廠模式、緩存了非常多實例、那么就得考慮效率問題,由于這個類一載入則把全部實例無論用不用一塊創建。 懶漢式的長處是延時載入、缺點是應該用同步。

單例模式的長處:
在內存中僅僅有一個對象。節省內存空間。
避免頻繁的創建銷毀對象,能夠提高性能。
避免對共享資源的多重占用。
能夠全局訪問。




適用場景:

因為單例模式的以上長處,所以是編程中用的比較多的一種設計模式。

我總結了一下我所知道的適合使用單例模式的場景:
須要頻繁實例化然后銷毀的對象。
創建對象時耗時過多或者耗資源過多,但又經經常使用到的對象。


有狀態的工具類對象。
頻繁訪問數據庫或文件的對象。
以及其它我沒用過的全部要求僅僅有一個對象的場景。


單例模式注意事項:
僅僅能使用單例類提供的方法得到單例對象,不要使用反射。否則將會實例化一個新對象。


不要做斷開單例類對象與類中靜態引用的危急操作。
多線程使用單例使用共享資源時,注意線程安全問題。

雙重鎖形式單例(懶漢式進階版。哈哈)

 public static class Singleton{private static Singleton instance=null;private Singleton(){//do something}public static Singleton getInstance(){if(instance==null){synchronized(Singleton.class){if(null==instance){instance=new Singleton();}}}return instance;}
}
(有些朋友搞不懂為什么要推斷兩次Instance==null,由于在多線程中第一次推斷時可能有兩個或者多個instance==null。那么在synchronized鎖里第一個instance已經new出來了,第二個或者后面進入的假設不推斷就會反復new對象出來,所以在里面多一層推斷確保Instance實例僅僅有一個)
這樣還是有一個缺點就是:就是在一個線程還未全然初始化該對象時,而那個變量已經顯示為被初始化,那么其它線程可能去使用這個未被全然初始化的實例,造成系統的崩潰。

只是這個在java5以上能夠安全執行。


第二種完美實現的實現既線程安全又延遲載入的模式(Initialization on demand holder)使用靜態內部類 ?演示樣例:

Public class Singleton{Private Singleton(){};Public static class Singleton1{Private static final Singleton instance = new Singleton();
}    Public static Singleton getInstance(){Return Singleton1.instance;
}
}

這樣就能保證在第一次調用getInstance()方法時,才會去初始化instance實例,并且該實例被定義為static,僅僅會被初始化一次。(這樣的方法是網上看的,我還未用過,以后能夠試試。哈哈大笑)

此文由本人從網上瀏覽總結而出。如需轉載,請注明出處,謝謝!





當一個類的實例能夠有且僅僅能夠一個的時候就須要用到了。為什么僅僅須要有一個呢?有人說是為了節約內存,但這僅僅是單例模式帶來的一個優點。僅僅有一個實例確實降低內存占用,但是我覺得這不是使用單例模式的理由。我覺得使用單例模式的時機是當實例存在多個會引起程序邏輯錯誤的時候。比方類似有序的號碼生成器這種東西,怎么能夠同意一個應用上存在多個呢?

轉載于:https://www.cnblogs.com/yfceshi/p/7061055.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371886.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371886.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371886.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python 32bit數據結構_python實現bitmap數據結構詳解

bitmap是很常見的算法設計,例如用以Bloom Filter中;用以無反復整數金額的排列這些。bitmap一般根據數組來完成,數組中每一個原素能夠當做是一系列二進制數,全部元素組成更高的二進制結合。針對Python而言,整數金額種類…

MVC如何使用開源分頁插件shenniu.pager.js

最近比較忙,前期忙公司手機端接口項目,各種開發調試發布現在幾乎上線無問題了;雖然公司項目忙不過在期間抽空做了兩件個人覺得有意義的事情,一者使用aspnetcore開發了個人線上項目(要說線上其實只能ip訪問,…

四. 基于環視Camera的BEV感知算法-PETR

目錄 前言0. 簡述1. 算法動機&開創性思路2. 主體結構3. 損失函數4. 性能對比5. PETRv2總結下載鏈接參考 前言 自動駕駛之心推出的《國內首個BVE感知全棧系列學習教程》,鏈接。記錄下個人學習筆記,僅供自己參考 本次課程我們來學習下課程第四章——基…

Java EE 6 VS Spring 3:Java EE已經殺死了Spring? 沒門!

介紹 幾天前,我在聽Java Spotlight Podcast的插曲85 。 在這次演講中, Bert Ertman和Paul Bakker討論了從Spring遷移到Java EE。 基本上,在他們的介紹中,他們說,如今,選擇Spring而不是Java EE是沒有意義的。…

usb檢測串口是哪個角_怎樣測試串口和串口線是否正常

一步:把串口線或者USB轉串口線插到計算機上。二步:打開串口調試助手接著選擇串口,串口線和 USB 轉串口的端口號查看路徑:電腦上--右鍵--屬性--硬件--設備管理器-端口(COM 和LPT),點開端口前面的號查看即可。注釋:1、US…

NodeJS常用模塊介紹

收集了NodeJS開發中常用的一些模塊。MVC框架 - Express Express 是輕量靈活的Nodejs Web應用框架,它可以快速地搭建網站。Express框架建立在Nodejs內置的Http模塊上,并對Http模塊再包裝,從而實際Web請求處理的 功能。它支持多種前端模板&…

Java泛型面試問題

Java面試中的通用面試問題在相當長的時間內在Java 5周圍越來越普遍,許多應用程序都轉移到Java 5上,并且幾乎所有新的Java開發都發生在Tiger(Java 5的代號)上。 泛型和Java 5功能(例如Enum)的重要性&#xf…

隱層元素閃一下_太陽一直依靠什么元素在燃燒,地球上的重元素又是怎么來的?...

本文基于回答網友一個這樣的問題:太陽目前氫核聚變是氦碳氧穩定燃燒地球上的鐵鎳重元素哪里來的?可以說,這是一個毫無邏輯亂七八糟的問題,但既然邀請回答,就從中挑出幾個稍顯合理的問題說明一下。太陽核心每時每刻都在…

基于Token的WEB后臺認證機制

基于Token的WEB后臺認證機制 幾種常用的認證機制 HTTP Basic Auth HTTP Basic Auth簡單點說明就是每次請求API時都提供用戶的username和password,簡言之,Basic Auth是配合RESTful API 使用的最簡單的認證方式,只需提供用戶名密碼即可&#xf…

JSF基于事件的溝通:過時的方法

用JSF編寫的Web應用程序由相互交互的bean組成。 在開發Web應用程序時,bean之間的通信是主要的設計模式之一。 有時,一個bean需要向其他bean發送事件,以通知它們某些更改或其他任何更改。 我們通常可以將托管bean或Spring bean注入另一個bean的…

mysql調優 基礎

MySQL調優可以從幾個方面來做:1. 架構層:做從庫,實現讀寫分離;2.系統層次:增加內存;給磁盤做raid0或者raid5以增加磁盤的讀寫速度;可以重新掛載磁盤,并加上noatime參數,這…

saltstack

第一:安裝前準備: 聲明我用的是ubuntu 16.04的系統 1.修改主機名,并保證兩臺機器可以互相ping同主機名 ip1 master_hostname ip2 slave_hostname 第二:安裝 服務器安裝 yum install salt-master -y客戶端安裝 yum install salt…

ios 百度地圖指定區域_獲取百度地圖可視區域范圍的數據

有個業務場景,需要根據獲取到的地圖區域顯示,根據相應的經緯度反查 左側區域的會議室。思路:1.得到百度地圖可視區域--可視區域的中心點2.可視區域的四個角的其中兩個(東北角西南角)http://lbsyun.baidu.com/cms/jsapi/reference/jsapi_refer…

使用WS-Trust / STS采樣器擴展JMeter

JMeter沒有對WS-Security或WS-Trust的任何內置支持,這使我為JMeter開發了此STS Sampler –可以在負載測試STS時使任何人的生活變得更好。 首先,您需要擁有Apache JMeter發行版。 我正在使用v2.7。 然后,您可以從此處下載sts.sampler.zip –解…

分享一個使用閉包對一個對象繼承方式

function Person(name,age){this.name name;this.age age; }//定義一個new函數 繼承了對Person的繼承 function New(obj){return function(){var o {"__proto__":obj.proto};obj.apply(o,arguments);}return obj; }var n new New(Person)("對象繼承了person…

vue怎么改logo_vue全家桶項目構建教程

前言vue是現階段很流行的前端框架,很多人通過vue官方文檔的學習,對vue的使用都有了一定的了解,但再在項目工程化處理的時候,卻發現不知道改怎么更好的管理自己的項目,如何去引入一些框架以及vue全家桶其他框架的使用&a…

EclipseLink MOXy作為JAXB提供者

EclipseLink MOXy是JAXB提供程序,并且是內置在JDK中的默認JAXB提供程序的引人注目的替代品。 首先是一個簡單的測試,將Java對象編組為XML: 這是模型: XmlRootElement(nameMemberDetailsRequest, namespacehttp://bk.org/members…

monkeyrunner多點觸摸

思路是:在屏幕上某個位置按著不放:device.touch(x,y,md.DOWN) 然后再做一個滑動的操作:device.drap((x1,y1),(x2,y2),0.2,10) 然后再松開按鍵:device.touch(x,y,md.UP) #codeing:utf-8 from com.android.monkeyrunner import Monk…

雅虎前端優化的35條軍規

閱讀目錄 內容部分css部分js部分javascript, css 圖片 cookie移動端 服務器摘要:無論是在工作中,還是在面試中,web前端性能的優化都是很重要的,那么我們進行優化需要從哪些方面入手呢?可以遵循雅虎的前端優化34條軍規&…

stm32 內部sram大小_在SRAM、FLASH中調試代碼的配置方法(附詳細步驟)

聊天界面發送嵌入式大雜燴獲取1TB大雜燴資料包STM32的FLASH擦寫次數有限(大概為1萬次),所以為了延長FLASH的使用時間,我們平時調試時可以選擇在SRAM中進行硬件調試。除此之外,SRAM 存儲器的寫入速度比在內部 FLASH 中要快得多,所以…