




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、PPT模板下載: 主講:張雷杰目的單例模式確保一個類僅有一個實例,且提供它的一個全局訪問點原因有時我們只想讓一個類的單個實例在系統(tǒng)中存在。我們需要讓該實例易于被訪問并且我們想要確保該類的其他實例不能被創(chuàng)建單例模式單例模式結(jié)構(gòu)單例模式優(yōu)點對惟一實例的受控訪問允許可變的實例數(shù)量能避免實例重復(fù)創(chuàng)建應(yīng)用于避免存在多個實例引起程序邏輯錯誤的場合較節(jié)約內(nèi)存單例模式的實現(xiàn)我們將使用靜態(tài)方法來允許客戶獲得對單個實例的引用,并且將使用私有構(gòu)造器!/* * Singleton類是只允許一個實例化的類的實現(xiàn) */public class Singleton / The private reference to th
2、e one and only instance.private static Singleton uniqueInstance = null;/ An instance attribute.private int data = 0;單例模式的實現(xiàn)/* * Returns a reference to the single instance. * Creates the instance if it does not yet exist. * (This is called lazy instantiation.) */public static Singleton instance() if(
3、uniqueInstance = null) uniqueInstance = new Singleton();return uniqueInstance; 單例模式的實現(xiàn)/* * The Singleton Constructor. * Note that it is private! * No client can instantiate a Singleton object! */private Singleton() / Accessors and mutators here!單例模式的實現(xiàn)以下是測試程序public class TestSingleton public static
4、void main(String args) / Get a reference to the single instance of Singleton.Singleton s = Singleton.instance();/ Set the data value.s.setData(34);System.out.println(First reference: + s);System.out.println(Singleton data value is: +s.getData();單例模式的實現(xiàn)/ Get another reference to the Singleton./ Is it
5、 the same object?s = null;s = Singleton.instance();System.out.println(nSecond reference: + s);System.out.println(Singleton data value is: +s.getData();outputsFirst reference: Singleton1cc810Singleton data value is: 34First reference: Singleton1cc810Singleton data value is: 34單例模式的實現(xiàn)注意:單例只在需要時才創(chuàng)建。這被稱
6、作被動實例化。如果兩個線程同時調(diào)用instance() 方法會怎么樣?會產(chǎn)生什么問題?思考實驗如何能預(yù)防這種情況哪?有幾個方法:單例模式的實現(xiàn)單例模式的實現(xiàn)下面是具有主動實例化的單例模式。我們將在靜態(tài)初始化器中創(chuàng)建Singleton實例。保證這種做法是線程安全的。/* * Singleton 類是只允許一個實例化的類的實現(xiàn)。 */public class Singleton / The private reference to the one and only instance. / Lets eagerly instantiate it here. private static Single
7、ton uniqueInstance = new Singleton(); / An instance attribute. private int data = 0;單例模式的實現(xiàn) /* * Returns a reference to the single instance. */ public static Singleton instance() return uniqueInstance; /* * The Singleton Constructor. * Note that it is private! * No client can instantiate a Singleton
8、 object! */ private Singleton() / Accessors and mutators here!主動實例化與被動實例化的區(qū)別主動實例化:在主動實例化:在uniqueInstance被加被加載時就將自己實例化。為靜態(tài)實例化方載時就將自己實例化。為靜態(tài)實例化方式。它在靜態(tài)初始化期間或在類的構(gòu)造式。它在靜態(tài)初始化期間或在類的構(gòu)造器中分配變量。類一加載就實例化,所器中分配變量。類一加載就實例化,所以要提前占用系統(tǒng)資源。以要提前占用系統(tǒng)資源。被動實例化在第一次被引用時,才會將被動實例化在第一次被引用時,才會將自己實例化。面臨多線程訪問的安全性自己實例化。面臨多線程訪問的安全性
9、問題,需要作雙重鎖定來保證安全。問題,需要作雙重鎖定來保證安全。具有子類的Singleton如果想要能夠生成Singleton的子類并讓單個實例是子類的實例時該怎么辦?例如,假定MazeFactory已生成子類 EnchantedMazeFactory 和 AgentMazeFactory。我們只想實例化一個工廠,或者EnchantedMazeFactory 或者是AgentMazeFactory。我們能怎樣做哪?有幾個方法:=由MazeFactory 的靜態(tài)instance() 方法決定某個子類的實例來實例化。這項工作能通過參數(shù)或環(huán)境變量來完成。在這種情況下子類的構(gòu)造器不能是私有的,因此客戶
10、端不能實例化子類的其他實例。=由每個子類提供一個靜態(tài)的instance() 方法?,F(xiàn)在子類的構(gòu)造器可以是私有的。具有子類的Singleton方法1方法1:由MazeFactory 的instance() 方法決定將實例化的子類/* * MazeFactory 類是只允許一個子類實例化的類的實現(xiàn) */public abstract class MazeFactory / The private reference to the one and only instance. private static MazeFactory uniqueInstance = null; / The MazeFa
11、ctory constructor. / If you have a default constructor, it can not be private / here! protected MazeFactory() 具有子類的Singleton方法1 / Return a reference to the single instance. / If instance not yet created, create enchanted as default. public static MazeFactory instance() if (uniqueInstance = null) ret
12、urn instance(enchanted); else return uniqueInstance; / Create the instance using the specified String name. 具有子類的Singleton方法1public static MazeFactory instance(String name) if (uniqueInstance = null) if (name.equals(enchanted)uniqueInstance = new EnchantedMazeFactory(); else if (name.equals(agent)un
13、iqueInstance = new AgentMazeFactory(); return uniqueInstance; 具有子類的Singleton方法1首先是創(chuàng)建工廠的客戶代碼:然后是訪問工廠的客戶代碼:注意:EnchantedMazeFactory和AgentMazeFactory 的構(gòu)造器不能是私有的,因為MazeFactory必須能夠?qū)嵗鼈?。因此,客戶不可能實例化這些子類的其他實例。MazeFactory factory = MazeFactory.instance(enchanted);MazeFactory factory = MazeFactory.instance();
14、具有子類的Singleton方法1(續(xù))The instance(String) 方法違反了開-閉原則,因為每個MazeFactory的新子類都必須修改它。public static MazeFactory instance(String name) if (uniqueInstance = null)uniqueInstance = Class.forName(name).newInstance();return uniqueInstance;我們可以將Java類名作為instance(String)方法的參數(shù)來使用,以產(chǎn)生更簡單的代碼:具有子類的Singleton方法2方法2: 由每個子類
15、提供一個靜態(tài)的instance() 方法/* * MazeFactory類是只允許一個子類實例化的類的實現(xiàn) * 該版本要求其子類提供靜態(tài)instance() 方法的實現(xiàn) */public abstract class MazeFactory / The protected reference to the one and only instance. protected static MazeFactory uniqueInstance = null; 具有子類的Singleton方法2 / The MazeFactory constructor. / If you have a defaul
16、t constructor, it can not be private / here! protected MazeFactory() / Return a reference to the single instance. public static MazeFactory instance() return uniqueInstance;具有子類的Singleton方法2 /* * Class EnchantedMazeFactory is an implementation of a class * that only allows one instantiation. */publi
17、c class EnchantedMazeFactory extends MazeFactory / Return a reference to the single instance. public static MazeFactory instance() if(uniqueInstance = null)uniqueInstance = new EnchantedMazeFactory(); return uniqueInstance; / Private subclass constructor! private EnchantedMazeFactory() 具有子類的Singleto
18、n方法2首先是創(chuàng)建工廠的客戶代碼:然后是訪問工廠的客戶代碼:注意:子類的構(gòu)造器現(xiàn)在是私有的。只能創(chuàng)建子類的一個實例!MazeFactory factory = EnchantedMazeFactory.instance();MazeFactory factory = MazeFactory.instance();也要注意到如果在惟一的實例被創(chuàng)建前客戶就調(diào)用MazeFactory.instance() ,客戶就能到一個null引用。最后,注意uniqueInstance 現(xiàn)在是被保護(hù)的!單例模式是應(yīng)用最廣的模式之一,確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例,應(yīng)用在一些創(chuàng)建
19、對象需要消耗較多資源的地方。定義單例模式實現(xiàn)方式1.懶漢模式,2.Double CheckLock(DCL)實現(xiàn)單例,3.靜態(tài)內(nèi)部類,4.枚舉單利,5.使用容器實現(xiàn)單例模式懶漢模式懶漢模式是申明一個靜態(tài)變量,在用戶首次調(diào)用getInstance時進(jìn)行初始化public class Singleton private static Singleton instance; private Singleton() public static synchronized Singleton getInstance() if(instance = null) instance = new Singleto
20、n(); return instance; 餓漢模式的話就在類加載的時候直接初始化 private static Singleton instance = new Singleton(); 每一次調(diào)用都需要進(jìn)行同步,造成不必要的開銷(一般不建議使用)DCL實現(xiàn)單例優(yōu)點是能夠在需要時才初始化,又能保證線程安全且單例對象初始化后調(diào)用getInstance不進(jìn)行同步鎖public class Singleton private static Singleton instance = null; private Singleton() public static Singleton getInstan
21、ce() if(instance = null) /主要為了避免不必要的同步 synchronized(Singleton.class) if(instance = null) /為了在空的情況下創(chuàng)建實例 instance = new Singleton(); return instance; DCL實現(xiàn)單例instance = new Singleton();的實際操作:1.給Singleton分配內(nèi)存,2調(diào)用Singleton的構(gòu)造函數(shù),初始化成員字段,3將instance對象指向分配的內(nèi)存空間但是Java編譯器允許處理器亂序執(zhí)行,已經(jīng)JDK1.5之前JMM(Java Memory Mod
22、el)中Cache,寄存器到主內(nèi)存回寫順序的規(guī)定執(zhí)行順序可能是123,也可能是132,如果是132就會出現(xiàn)instance不是空,但是使用的時候會有問題,1.6開始已經(jīng)作了調(diào)整,利用Private volatile static Singleton instance = null;就可以保證安全性,但是會消耗一些性能優(yōu)點:資源資源利用率高,是使用最多的單利實現(xiàn)方式,可以滿足絕大多數(shù)的單例,但是在一些高并發(fā)或者JDK1.6版本以下使用會有創(chuàng)建失敗的可能性靜態(tài)內(nèi)部類DCL存在一定的失效問題,所以不贊成使用,建議使用如下代碼代替:public class Singleton private Sing
23、leton() public static Singleton getInstance() return SingletonHolder.sInstance; /*靜態(tài)內(nèi)部類*/ private static SingletonHolder private static final Singleton sInstance = new Singleton();第一次加載Singleton時不會初始化sInstance,只有第一次調(diào)用getInstance的時候才會初始化,因此導(dǎo)致虛擬機(jī)加載SingletonHolder類,這種方式不僅能保證線程安全,也能保證唯一性和延遲加載,推薦使用枚舉單例默認(rèn)
24、枚舉類實例是線程安全的,并且在任何情況下它都是一個單例public enum SingletonEnum() INSTANCE; public void doSomething() System.out.println(=); 反序列化:在上述的集中單例模式中,反序列化會導(dǎo)致對象的重新創(chuàng)建(即使構(gòu)造方法是私有的也會),但是反序列化操作提供了一個很特別的函數(shù)readResolve(),這個方法可以控制對象的反序列化;private Object readResolve() throws ObjectStreamException return sInstance;使用容器實現(xiàn)單例模式在程序初始化
25、的時候?qū)⒍喾N單例類注入到統(tǒng)一的管理類中,再用key進(jìn)行獲取public class SingletonManager private static Map objMap = new HashMap(); private Singleton() public static void registerService(String key, Object instance) if (!objMap.containsKey(key) objMap.put(key,instance); public static Object getService(String) return objMap.get(k
26、ey); Java實例-系統(tǒng)日志(續(xù))幾乎所有的系統(tǒng)都需要日志記錄,其設(shè)計的原理就是采用單例模式,用文件提供日志記錄,所有關(guān)聯(lián)的日志都記錄在同一個文件中。其實現(xiàn)的代碼如下Public class Client public static void main(String args) /初始化 Logger Logger.initialize(); /獲得實例 Logger loger=Logger.getLogger(); loger.logMsg(“client log message”); 先看客戶調(diào)用程序:Logger.initialize();Java實例-系統(tǒng)日志(續(xù))import
27、java.text.SimpleDateFormat;import java.util.GregorianCalendar;import java.util.Properties;import java.io.InputStream;import java.io.FileOutputStream;import java.io.PrintStream;import java.io.IOException;public class Logger private String fileName; private Properties properties; private Priority prio
28、rity; Logger的詳細(xì)調(diào)用:Java實例-系統(tǒng)日志(續(xù))/* * Private constructor構(gòu)造函數(shù)是私有的,因此,此類不能被繼承 */ private Logger () logger = this; /* * 日志級別:錯誤或信息等 * * return level, int */ public int getRegisteredLevel () int i = 0; private Logger () logger = this; Java實例-系統(tǒng)日志(續(xù))try InputStream inputstream = getClass ().getResourceAs
29、Stream ( Lperties); properties.load (inputstream); inputstream.close (); i = Integer.parseInt (properties.getProperty ( *logger.registeredlevel*); if (i 3) i = 0; catch (Exception exception) System.out.println (Logger: Failed in the getRegisteredLevel method);Java實例-系統(tǒng)日志(續(xù)) exception.printS
30、tackTrace (); return i;/* * One file will be made daily. So, putting date time in file * name. * * param gc GregorianCalendar * return String, name of file */private String getFileName (GregorianCalendar gc) SimpleDateFormat dateFormat1 = new SimpleDateFormat (dd-MMM-yyyy);Java實例-系統(tǒng)日志(續(xù)) String dateString = dateFormat1.format (g
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 租借儲罐協(xié)議書
- 財產(chǎn)分清協(xié)議書
- 教學(xué)工作室合同協(xié)議書
- 聘用養(yǎng)花協(xié)議書
- 用電合伙協(xié)議書
- 管理導(dǎo)購協(xié)議書
- 正規(guī)勞務(wù)工合同協(xié)議書
- 收購二手房合伙協(xié)議書
- 職工死亡協(xié)議書
- 調(diào)解病房協(xié)議書
- 吉林省長春市2025屆高三質(zhì)量監(jiān)測(四)英語試卷+答案
- “成于大氣 信達(dá)天下”-成信校史課程知到課后答案智慧樹章節(jié)測試答案2025年春成都信息工程大學(xué)
- 鋼箱梁焊接作業(yè)指導(dǎo)書
- GB 34660-2017道路車輛電磁兼容性要求和試驗方法
- BB/T 0034-2017鋁防盜瓶蓋
- 國家義務(wù)教育質(zhì)量監(jiān)測科學(xué)模擬測試題附答案
- 12-1限度樣品管理辦法
- UI界面設(shè)計交互設(shè)計教學(xué)
- 主要股東或出資人信息及投標(biāo)人基本情況表模板
- 鋼箱梁計算分析與案例詳解
- 絞肉機(jī)的設(shè)計本科生畢業(yè)論文
評論
0/150
提交評論