懶漢單例模式java
㈠ java的單例模式到底有幾種變現形式請列舉
JAVA單例模式的幾種實現方法
1.餓漢式單例類
package pattern.singleton;
//餓漢式單例類.在類初始化時,已經自行實例化
public class Singleton1 {
//私有的默認構造子
private Singleton1() {}
//已經自行實例化
private static final Singleton1 single = new Singleton1();
//靜態工廠方法
public static Singleton1 getInstance() {
return single;
}
}
2.懶漢式單例類
package pattern.singleton;
//懶漢式單例類.在第一次調用的時候實例化
public class Singleton2 {
//私有的默認構造子
private Singleton2() {}
//注意,這里沒有final
private static Singleton2 single;
//只實例化一次
static{
single = new Singleton2();
}
//靜態工廠方法
public synchronized static Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
在上面給出懶漢式單例類實現里對靜態工廠方法使用了同步化,以處理多線程環境。有些設計師在這里建議使用所謂的"雙重檢查成例".必須指出的是,"雙重檢查成例"不可以在Java 語言中使用。不十分熟悉的讀者,可以看看後面腔或給出的小節。 同樣液者,由於構造子是私有的,因此,此類不能被繼承。餓漢式單例類在自己被載入時就將自己實例化。即便載入器是靜態的,在餓漢式單例類被載入時仍會將自己實例化。單從資源利用效率角度來講,這個比懶漢式單例類稍差些。從速度和反應時間角度來講,則比懶漢式單例類稍好些。然而,懶漢式單例類在實例化時,必須處
理好在多個線程同時首次引用此類時的訪問限制問題,特別是當單例類作為資源控制器,在實例化時必然涉及資源初始化,而資源初始化很有可能耗費時間。這意味著出現多線程同時首次引用此類的機率變得較大。
餓漢式單例類可以在Java 語言內實現, 但不易在C++ 內實現,因為靜態初始化在C++ 里沒有固定的順序,因而靜態的m_instance 變數的初始化與類的載入順序沒有保證,可能會出問題。這就是為什麼GoF 在提出單例類的概念時,舉的例子是懶漢式的。他們的書影響之大,以致Java 語言中單例類的例子也大多是懶漢式的。實際上,本書認為餓漢式單例類更符合Java 語言本身的特點。
3.登記式單例類.
package pattern.singleton;
import java.util.HashMap;
import java.util.Map;
//登記式單例類.
//類似Spring裡面的方法,將類名注冊,下次從裡面直接獲取。
public class Singleton3 {
private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保護的默認構伍埋伍造子
protected Singleton3(){}
//靜態工廠方法,返還此類惟一的實例
public static Singleton3 getInstance(String name) {
if(name == null) {
name = Singleton3.class.getName();
System.out.println("name == null"+"--->name="+name);
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton3) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
//一個示意性的商業方法
public String about() {
return "Hello, I am RegSingleton.";
}
public static void main(String[] args) {
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}
㈡ 請教 Java設計模式中的單例模式的懶漢式和餓漢式名字的由來,為什麼叫懶漢式 餓漢式
所謂「舉襪懶漢式正滑激」與「餓漢式」的區別,是在與建立單例對象的時間不同。
「懶漢式」是在你真正用到的時候才去建這個單例對象:
比如:有個單例對象
private static Student student = null; //不建立對象
Student getInstance(){
if(student == null) { //先判斷是否為空
student = new Student(); //懶漢式做法
}
return student;
}
「餓漢式」是在不管你用的用不上,一開始就建立這個單例對象:
比如:有個單例對象
private static Student student = new Student(); //建立對象
Student getInstance(){
return student; //直接返回單例對讓鎮象
}
㈢ JAVA單例模式有哪些
一、懶漢式單例x0dx0a在類載入的時候不創建單例實例。只有在第一次請求實例的時候的時候創建,並且只在第一次創建後,以後不再創建該類的實例。x0dx0a x0dx0apublic class LazySingleton {x0dx0a /**x0dx0a * 私有靜態對象,載入時候不做初始化x0dx0a */x0dx0a private static LazySingleton m_intance=null;x0dx0a /**x0dx0a * 私有構造方法,避免外部創建實例x0dx0a */x0dx0a private LazySingleton(){x0dx0a }x0dx0a /**x0dx0a * 靜態工廠方法,返回此類的唯一實例. x0dx0a * 當發現實例沒有初始化的時候,才初始化.x0dx0a */x0dx0a synchronized public static LazySingleton getInstance(){x0dx0a if(m_intance==null){x0dx0a m_intance=new LazySingleton();x0dx0a }x0dx0a return m_intance;x0dx0a }x0dx0a}x0dx0ax0dx0a二、餓漢式單例x0dx0a在類被載入的時候,唯一實例已經被創建。x0dx0a x0dx0apublic class EagerSingleton {x0dx0a /**x0dx0a * 私有的(private)唯一(static final)實例成員,在類載入的時候就創建好了單例對象x0dx0a */x0dx0a private static final EagerSingleton m_instance = new EagerSingleton();x0dx0a /**x0dx0a * 私有構造方法,避免外部創建實例x0dx0a */x0dx0a private EagerSingleton() {x0dx0a }x0dx0a /**x0dx0a * 靜態工廠方法,返回此類的唯一實例.x0dx0a * @return EagerSingletonx0dx0a */x0dx0a public static EagerSingleton getInstance() {x0dx0a return m_instance;x0dx0a }x0dx0a}x0dx0a x0dx0a************************************************************************************** 懶漢方式,指全局的單例實例在第一次被使用時構建; x0dx0a餓漢方式,指全局的單例實例在類裝載時構建 x0dx0a**************************************************************************************x0dx0ax0dx0a三、登記式單例x0dx0a這個單例實際上維護的是一組單例類的實例,將這些實例存放在一個Map(登記薄)中,對於已經登記過的實例,則從工廠直接返回,對於沒有登記的,則先登記,而後返回。x0dx0apublic class RegSingleton {x0dx0a /**x0dx0a * 登記薄,用來存放所有登記的實例x0dx0a */x0dx0a private static Map
㈣ Java單例模式是什麼意思
Java單例模式是確保某個類只有一個實例,而且自行實例化並向整個系統提供這個實例,在計算機系統中,線程池、緩存、日誌對象、對話框、列印機、顯卡的驅動程序對象常被設計成單例的模式;
Java單例模式分三種:懶漢式單例、餓漢式單例、登記式單例。
㈤ java里的單例模式是不是就是相當於c中的全局
個人理解,是的,java的單例模式代表只有一個對象的建立,和C裡面的全局變數是一個意思
㈥ java 中 單實例和多實例是指的什麼
簡單的說單例就是
只能有一個實例,所以地方用到的實例都是同一個。
就好像家人吃飯,桌子是單例的,大家用的是同一個。而碗是多例的,每人都有自幾的。
下面是具體的例子:
Java模式之單例模式:
單例模式確保一個類只有一個實例,自行提供這個實例並向整個系統提供這個實例。
特點:
1,一個類只能有一個實例
2,自己創建這個實例
3,整個系統都要使用這個實例
例:
在下面的對象圖中,有一個"單例對象",而"客戶甲"、"客戶乙"
和"客戶丙"是單例對象的三個客戶對象。可以看到,所有的客戶對象共享一個單例對象。而且從單例對象到自身的連接線可以看出,單例對象持有對自己的引用。
Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。在很多操作中,比如建立目錄
資料庫連接都需要這樣的單線程操作。一些資源治理器經常設計成單例模式。
外部資源:譬如每台計算機可以有若干個列印機,但只能有一個Printer
Spooler,以避免兩個列印作業同時輸出到列印機中。每台計算機可以有若干個通信埠,系統應當集中治理這些通信埠,以避免一個通信埠被兩個請求同時調用。內部資源,譬如,大多數的軟體都有一個(甚至多個)屬性文件存放系統配置。這樣的系統應當由一個對象來治理這些屬性文件。一個例子:Windows
回收站。
在整個視窗系統中,回收站只能有一個實例,整個系統都使用這個惟一的實例,而且回收站自行提供自己的實例。因此,回收站是單例模式的應用。
兩種形式:
1,餓漢式單例類
public
class
Singleton
{
private
Singleton(){}
//在自己內部定義自己一個實例,是不是很希奇?
//注重這是private
只供內部調用
private
static
Singleton
instance
=
new
Singleton();
//這里提供了一個供外部訪問本class的靜態方法,可以直接訪問
public
static
Singleton
getInstance()
{
return
instance;
}
}
2,懶漢式單例類
public
class
Singleton
{
private
static
Singleton
instance
=
null;
public
static
synchronized
Singleton
getInstance()
{
//這個方法比上面有所改進,不用每次都進行生成對象,只是第一次
//使用時生成實例,提高了效率!
if
(instance==null)
instance=new
Singleton();
return
instance;
}
}
第二中形式是lazy
initialization,也就是說第一次調用時初始Singleton,以後就不用再生成了。
注重到lazy
initialization形式中的synchronized,這個synchronized很重要,假如沒有synchronized,那麼使用getInstance()是有可能得到多個Singleton實例。
一般來說第一種比較安全。進入討論組討論。
㈦ JAVA單例模式有哪些
一、懶漢式單例
在類載入的時候不創建單例實例。只有在第一次請求實例的時候的時候創建,並且只在第一次創建後,以後不再創建該類的實緩拍李例。
public class LazySingleton {
/**
* 私有靜態對象,載入時候不做初始化
*/
private static LazySingleton m_intance=null;
/**
* 私有構造方法,避免外部創建實例
*/
private LazySingleton(){
}
/**
* 靜態工廠方法,返回此類的唯一實例.
* 當發現實例沒有初始化的時候,才初始化.
*/
synchronized public static LazySingleton getInstance(){
if(m_intance==null){
m_intance=new LazySingleton();
}
return m_intance;
}
}
二、餓漢式單例
在類被載入的時候,唯一實例已經被創建。
public class EagerSingleton {
/**
* 私有的(private)唯一(static final)實例成員,在類載入的時候就擾遲創建好了單例對象
*/
private static final EagerSingleton m_instance = new EagerSingleton();
/**
* 私有構造方法,避免外部創建實例
*/
private EagerSingleton() {
}
/**
* 靜態工廠方法,返回此類的唯一實例.
* @return EagerSingleton
*/
public static EagerSingleton getInstance() {
return m_instance;
}
}
************************************************************************************** 懶漢方式,指全局的單例實例在第一次被使用時構建;
餓漢方式,指全局的單例實例在類裝載時構建
**************************************************************************************
三、登記式單例
這個單例實際上維護的是一組單例類的實例,將這些實例存放在一個Map(登記薄)中,對於已經登記過的實例,則從工廠直接返回,對於沒有登記的,則先登記,而後返回。賀並
public class RegSingleton {
/**
* 登記薄,用來存放所有登記的實例
*/
private static Map<String, RegSingleton> m_registry = new HashMap();
//在類載入的時候添加一個實例到登記薄
static {
RegSingleton x = new RegSingleton();
m_registry.put(x.getClass().getName(), x);
}
/**
* 受保護的默認構造方法
*/
protected RegSingleton() {
}
/**
* 靜態工廠方法,返回指定登記對象的唯一實例;
* 對於已登記的直接取出返回,對於還未登記的,先登記,然後取出返回
* @param name
* @return RegSingleton
*/
public static RegSingleton getInstance(String name) {
if (name == null) {
name = "RegSingleton";
}
if (m_registry.get(name) == null) {
try {
m_registry.put(name, (RegSingleton) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return m_registry.get(name);
}
/**
* 一個示意性的商業方法
* @return String
*/
public String about() {
return "Hello,I am RegSingleton!";
}
}
㈧ JAVA中單例模式懶漢式 成員變數為什麼要賦值為空成員變數虛擬機不是會給它自動賦值么
應該是一種習慣,其次可能是因為他是靜態的,靜態的變數,無論類被實例化幾次,他的值都是不會改變的,照你這么說,成員變數余緩會自動粗慎賦值,但是他的值在實例化N次之後並沒有變化,總的來說,這是這個種好習慣,就怕不同平台賦予的初始值豎凳模不相同。
㈨ java如何只存一次數據
在Java中只存儲一次數據可以使用單例模式來弊升實現。單例模式是一種常用的設計模式,它可以保證一個類只租氏老核明有一個實例,並提供一個全局訪問點。在實現單例模式時,一般採用懶漢式或餓漢式兩種方式。
1、餓漢式單例模式:在類載入時就創建實例。
2、懶漢式單例模式:在第一次使用時才創建實例。
㈩ Java模式設計之單例模式(一)
作為對象的創建模式[GOF ] 單例模式確保某一個類只有一個實例 而且自行實例化並向整個系統提供這個實例 這個類稱為單例類
單例模式的要點
單例單例
顯然單例模式的要點有三個 一是某各類只能有一個實例 二是它必須自行創建這個事例 三是它必須自行向整個系統提供這個實例 在下面的對象圖中 有一個 單例對象 而 客戶甲 客戶乙 和 客戶丙 是單例對象的三個客戶對象 可以看到 所有的客戶對象共享一個單例對象 而且從單例對象到自身的連接線可以看出 單例對象持有對自己的引用
資源管理
一些資源管理器常常設計成單例模式
在計算機系統中 需要管理的資源包括軟體外部資源 譬如每台計算機可以有若干個列印機 但只能有一個Printer Spooler 以避免兩個列印作業同時輸出到列印機中 每台計算機可以有若干傳真卡 但是只應該有一個軟體負責管理傳真卡 以避免出現兩份傳真作業同時傳到傳真卡中的情況 每台計算機可以有若干通信埠 系統應當集中管理這些通信埠 以避免一個通信埠同時被兩個請求同時調用
需要管理的資源包括軟體內部資源 譬如 大多數的軟體都有一個(甚至多個)屬性(properties)文件存放系統配置 這樣的系統應當由一個對象來管理一個屬性文件
需要管理的軟體內部資源也包括譬如負責記錄網站來訪人數的部件 記錄軟體系統內部事件 出錯信息的部件 或是對系統的表念螞現進行檢查的部件等 這些部件都必須集中管理 不可政出多頭
這些資源管理器構件必須只有一個實例 這是其一 它們必須自行初始化 這是其二 允許整個系統訪問自己這是其三 因此 它們都滿足單例模式的條件 是單例模式的應用
一個例子 Windows 回收站
Windows x 以後的視窗系統中都有一個回收站 下圖就顯示了Windows 的回收站
在整個視窗系塵高核統中 回收站只能有一個實例 整個系統都使用這個惟一的實例 而且回收站自行提供自己的實例 因此 回收站是單例模式的應用
雙重檢查成例
在本章最後的附錄里研究了雙重檢查成例 雙重檢查成例與單例模式並無直接的關系 但是由於很多C 語言設計師在單例模式裡面使用雙重檢查成例 所以這一做法也被很多Java 設計師所模仿 因此 本書在附錄里提醒讀者 雙重檢查成例在Java 語言里並不能成立 詳情請見本章的附錄
單例模式的結構
單例模式有以下的特點
…… 單例類只可有一個實例
…… 單例類必須自己創建自己這惟一的實例
…… 單例類必須給所有其他對象提供這一實例
雖然單例模式中的單例類被限定只能有一個實例 但是單例模式和單例類可以很容易被推廣到任意且有限多個實例的情況 這時候稱它為多例模式(Multiton Pattern) 和多例類(Multiton Class) 請見 專題 多例(Multiton )模式與多語言支持 一章 單例類的簡略類圖如下所示
由於Java 語言的特點 使得單例模式在Java 語言的實現上有自己的特點 這些特點主要表現在單例類如何將自己實例化上
餓漢式單例類餓漢式單例類是在Java 語言里實現得最為簡便的單例類 下面所示的類圖描述了一個餓漢式單例類的典型實現
從圖中可以看出 此類已經自已將自己實例化
代碼清單 餓漢式單例類
public class EagerSingleton { private static final EagerSingleton m_instance = new EagerSingleton() /** * 私有的默認構造子*/ private EagerSingleton() { } /** * 靜態工廠方法*/ public static EagerSingleton getInstance()
{
Java 與模式return m_instance }
讀者可以看出 在這個類被載入時 靜態變數m_instance 會被初始化 此時類的私有構造子會被調用 這時候 單例類的惟一實例就被創建出來了
Java 語言中單例類的一個最重要的特點是類派掘的構造子是私有的 從而避免外界利用構造子直接創建出任意多的實例 值得指出的是 由於構造子是私有的 因此 此類不能被繼承
懶漢式單例類
與餓漢式單例類相同之處是 類的構造子是私有的 與餓漢式單例類不同的是 懶漢式單例類在第一次被引用時將自己實例化 如果載入器是靜態的 那麼在懶漢式單例類被載入時不會將自己實例化 如下圖所示 類圖中給出了一個典型的餓漢式單例類實現
代碼清單 懶漢式單例類
package javapatterns singleton demos public class LazySingleton { private static LazySingleton m_instance = null /** * 私有的默認構造子 保證外界無法直接實例化*/ private LazySingleton() { } /** * 靜態工廠方法 返還此類的惟一實例*/ synchronized public static LazySingleton getInstance()
{ if (m_instance == null)
{ m_instance = new LazySingleton() } return m_instance }
讀者可能會注意到 在上面給出懶漢式單例類實現里對靜態工廠方法使用了同步化 以處理多線程環境 有些設計師在這里建議使用所謂的 雙重檢查成例 必須指出的是 雙重檢查成例 不可以在Java 語言中使用 不十分熟悉的讀者 可以看看後面給出的小節
同樣 由於構造子是私有的 因此 此類不能被繼承 餓漢式單例類在自己被載入時就將自己實例化 即便載入器是靜態的 在餓漢式單例類被載入時仍會將自己實例化 單從資源利用效率角度來講 這個比懶漢式單例類稍差些
從速度和反應時間角度來講 則比懶漢式單例類稍好些 然而 懶漢式單例類在實例化時 必須處理好在多個線程同時首次引用此類時的訪問限制問題 特別是當單例類作為資源控制器 在實例化時必然涉及資源初始化 而資源初始化很有可能耗費時間 這意味著出現多線程同時首次引用此類的機率變得較大
餓漢式單例類可以在Java 語言內實現 但不易在C++ 內實現 因為靜態初始化在C++ 里沒有固定的順序 因而靜態的m_instance 變數的初始化與類的載入順序沒有保證 可能會出問題 這就是為什麼GoF 在提出單例類的概念時 舉的例子是懶漢式的 他們的書影響之大 以致Java 語言中單例類的例子也大多是懶漢式的 實際上 本書認為餓漢式單例類更符合Java 語言本身的特點
登記式單例類
登記式單例類是GoF 為了克服餓漢式單例類及懶漢式單例類均不可繼承的缺點而設計的 本書把他們的例子翻譯為Java 語言 並將它自己實例化的方式從懶漢式改為餓漢式 只是它的子類實例化的方式只能是懶漢式的 這是無法改變的 如下圖所示是登記式單例類的一個例子 圖中的關系線表明 此類已將自己實例化
代碼清單 登記式單例類
import java util HashMap public class RegSingleton { static private HashMap m_registry = new HashMap() static { RegSingleton x = new RegSingleton() m_registry put( x getClass() getName() x) } /** * 保護的默認構造子*/ protected RegSingleton() {} /** * 靜態工廠方法 返還此類惟一的實例*/ static public RegSingleton getInstance(String name)
{ if (name == null)
{ name = javapatterns singleton demos RegSingleton } if (m_registry get(name) == null)
{ try { m_registry put( name Class forName(name) newInstance() ) } catch(Exception e)
{ System out println( Error happened ) } return (RegSingleton) (m_registry get(name) ) } /** * 一個示意性的商業方法*/ public String about()
{ return Hello I am RegSingleton }它的子類RegSingletonChild 需要父類的幫助才能實例化 下圖所示是登記式單例類子類的一個例子 圖中的關系表明 此類是由父類將子類實例化的
下面是子類的源代碼
代碼清單 登記式單例類的子類
import java util HashMap public class RegSingletonChild extends RegSingleton { public RegSingletonChild() {} /** * 靜態工廠方法*/ static public RegSingletonChild getInstance()
{ return (RegSingletonChild)
RegSingleton getInstance( javapatterns singleton demos RegSingletonChild ) } /** * 一個示意性的商業方法*/ public String about()
{ return Hello I am RegSingletonChild }
在GoF 原始的例子中 並沒有getInstance() 方法 這樣得到子類必須調用的getInstance(String name)方法並傳入子類的名字 因此很不方便 本章在登記式單例類子類的例子里 加入了getInstance() 方法 這樣做的好處是RegSingletonChild 可以通過這個方法 返還自已的實例 而這樣做的缺點是 由於數據類型不同 無法在RegSingleton 提供這樣一個方法 由於子類必須允許父類以構造子調用產生實例 因此 它的構造子必須是公開的 這樣一來 就等於允許了以這樣方式產生實例而不在父類的登記中 這是登記式單例類的一個缺點
lishixin/Article/program/Java/gj/201311/27416