免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式

       這是我寫模式設(shè)計的第二篇,首先來說說設(shè)計模式的分類。

       基本的23種設(shè)計模式從目的上可分為三種:

1、  創(chuàng)建型(Creational)模式:負(fù)責(zé)對象創(chuàng)建。

2、  結(jié)構(gòu)型(Structural)模式:處理類與對象間的組合,可以解決一些繼承依賴性的問題

3、  行為型(Behavioral)模式:類與對象交互中的職責(zé)分配,可以解決組件間如何和交互,隔離變化。

下面來說說單件模式:

首先說說單件模式產(chǎn)生的動機,也就是為什么會出現(xiàn)單件模式。有一些類在系統(tǒng)中只存在一個實例才能確保他們的邏輯正確性以及良好的效率。這時我想到我遇到的一個問題。我曾經(jīng)遇到一個WinForm程序,運行后出現(xiàn)一個登陸框,輸入用戶名密碼后點擊登陸,然后顯示一個登陸后的界面。但是點擊登陸后,程序要做一些操作,由于這段操作用時相對較長,在不經(jīng)意時,我有點擊了一次登陸按鈕,最后出現(xiàn)了兩個對話框。如:我現(xiàn)在有兩個Form窗體Form1Form2。Form1上有一個按鈕用來打開Form2并隱藏自己。我們可以這樣寫:

         private void button1_Click(object sender, System.EventArgs e)

        {

            Form2 form = new Form2();

            form.Show();

            this.Hide();

    }

如果我們在顯示Form2前由一些比較耗時的操作。如:我們讓線程的沉睡10秒在顯示Form2,當(dāng)我們在線程沉睡時繼續(xù)點擊Form1上的Button,有可能就會出現(xiàn)兩個Form2的窗體。(我試過可以出現(xiàn)兩個Form2,如果你有心試但沒事出來別拿西紅柿砍我,哈哈)

        private void button1_Click(object sender, System.EventArgs e)

        {

            Thread.Sleep(10000);

            Form2 form = new Form2();

            form.Show();

            this.Hide();

    }

這種情況出現(xiàn)不能怪客戶多點了一下,也不能說是編譯器不夠智能,應(yīng)該是我們程序上的Bug,我想這種情況用單件模式應(yīng)該可以解決。

單件模式的使用意圖就是:保證一個類僅有一個實例,并提供一個該實例全局的訪問點(這句話當(dāng)然不是我先說的,是引用Gof在《設(shè)計模式》中的一句話)

那類的設(shè)計者如何繞過常規(guī)的構(gòu)造器來實現(xiàn)單件模式呢?下面就來談?wù)剢渭J降膶崿F(xiàn)。

單件模式在結(jié)構(gòu)上使用了景泰方法來約束構(gòu)造器(也就是構(gòu)造函數(shù))創(chuàng)建對象。

在單線程的情況下:私有化構(gòu)造函數(shù),使類的使用者調(diào)用不到這個構(gòu)造函數(shù)來new一個實例。類型中可以自己new一個實例。類中創(chuàng)建一個靜態(tài)私有變量和Static公有屬性。在公有屬性中實現(xiàn)此類的實例化。這樣在第一次請求時創(chuàng)建此對象。代碼如下:

class Singleton

    {

        private static Singleton _instance;

       

        private Singleton(){}

 

        public static Singleton f_Instance

        {

            get

            {

                if(_instance == null)

                {

                    _instance = new Singleton();

                }

                return _instance;

            }

        }

    }

我在main函數(shù)中寫入如下程序來查看一下這樣寫是否有效:

static void Main(string[] args)

        {

            Singleton t1 = Singleton.f_Instance;

            Singleton t2 = Singleton.f_Instance;

            Console.Write(object.ReferenceEquals(t1,t2));

            Console.Read();

        }

控制臺顯示為True,開來還是有效的。當(dāng)然在Main中我也試過這樣寫:Singleton t1 = new Singleton(),編譯時告訴我Singleton()不可訪問(當(dāng)然,人家是私有的,不是自家人當(dāng)然不見)

這種單線程下的單件模式有幾點要注意:

1、  構(gòu)造器私有化(如果要此類被繼承,可以用protected聲明構(gòu)造器)

2、  不要支持IClinieable接口,因為會導(dǎo)致多個對象實例的出現(xiàn)

3、  不能支持序列化

4、  單件模式只考慮了對象創(chuàng)建的管理,沒有考慮對象的銷毀管理(創(chuàng)建自己的對象,銷毀的事交給垃圾回收器吧)

5、  不能應(yīng)對多線程環(huán)境,因為會導(dǎo)致多個對象實例的出現(xiàn)

那在多線程下如何實現(xiàn)呢?代碼如下:

class SingletonMuli//多線程Singleton模式

    {

        private static volatile SingletonMuli _instance;    //volatile是為了讓編譯器對此代碼編譯后的位置不進行調(diào)整

        private SingletonMuli(){}

        private static object lockHelper = new object();    //輔助器,不參與對象構(gòu)建

        public static SingletonMuli f_Instance

        {

            get

            {

                if(_instance == null)

                {

                    lock(lockHelper)

                    {

                        if(_instance == null)       //雙檢查

                        {

                            _instance = new SingletonMuli();

                        }

                    }

                }

                return _instance;

            }

        }

    }

當(dāng)然還有一些更簡單的實現(xiàn)方法,如:

    class Singleton1//可以用在多線程環(huán)境

    {

        public static readonly Singleton1 _instance = new Singleton1();

        private Singleton1(){}

    }

其中要提到的是在_instance私有字段的實例化叫做“內(nèi)聯(lián)初始化”。內(nèi)聯(lián)初始化是指在聲明時。

實際上面的代碼上相當(dāng)于如下代碼:

Public static readonly Singleton1 _instance;

Static Singleton()  //靜態(tài)構(gòu)造函數(shù)

{

    _instance = new Singleton();        //私有構(gòu)造器

}

Private Singleton(){}

內(nèi)聯(lián)初始化時會先執(zhí)行靜態(tài)構(gòu)造器,如果沒有靜態(tài)構(gòu)造函數(shù),系統(tǒng)會默認(rèn)一個。在訪問此靜態(tài)字段時執(zhí)行靜態(tài)構(gòu)造器生成。靜態(tài)構(gòu)造器保證了在多線程時只有一個線程執(zhí)行,自動加鎖。

當(dāng)然,第二種實現(xiàn)方式也有一些缺點,如:靜態(tài)構(gòu)造器必須是私有的、無參的。不過也可以用其他的方式解決這類問題。如可以用方法屬性實現(xiàn)擴展或修改私有構(gòu)造器。

現(xiàn)在我們可以回來看看我開始說的那兩個Form的問題,我們現(xiàn)在可以這樣實現(xiàn):

        private static Form2 form;

 

        private void button1_Click(object sender, System.EventArgs e)

        {

            Thread.Sleep(10000);

            object lockhelp = new object();

            if(form == null)

            {

                lock(lockhelp)

                {

                    if(form == null)

                    {

                        form = new Form2();

                        form.Show();

                    }

                }

            }

            this.Hide();

        }

這樣問題就解決了(我是沒有點出來第二個Form2,如果那位點出來了,給我發(fā)Email,我請她/他在天津的烤鴨)

單件模式實際上是利用控制對象創(chuàng)造過程來控制對象的創(chuàng)造個數(shù)的方法,我們可以對其進行擴展,不是讓他只生成一個對象,可以讓他只生成幾個對象,這樣可以實現(xiàn)對象池。

單件模式的核心是:如何控制用戶使用new對一個類的實例構(gòu)造器的任意調(diào)用。

 

posted on 2006-04-16 17:04 KiddLee 閱讀(1623) 評論(18)  編輯 收藏 引用 網(wǎng)摘 所屬分類: 設(shè)計模式

FeedBack:
# 
private static object lockHelper = new object();
你知道為什么要這樣寫嗎?

而且,能顯示兩個窗體,正是EventHandler注冊了多個委托實例的原因,
你修改后的button1_Click也并不是單件模式的應(yīng)用.  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-16 18:12 Dflying Chen
我也看不懂您的例子中Singleton的實現(xiàn)。  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-16 23:05 bisou.cn
剛開始看設(shè)計模式,有個疑問就是Singleton和不用Singleton模式的類有什么區(qū)別?就是一個能夠保證一個實例,一個不能保證嗎?如果這樣的話大多類不都可以用這種形式來做?除了一些特殊情況外?可為什么我看別人的代碼還是充斥著許多new呢?是他們不會用還是其他??
望賜教  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 08:39 Terrylee
@bisou.cn
并不是大多數(shù)類都要用Singleton模式的,應(yīng)該是大多數(shù)類都不用的,而只是那些少數(shù)資源比較昂貴的類才會用!  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 08:51 kid_li
@aaaaaaa
修改后的代碼我沒有拷貝完全,private static object lockHelper = new object();這句代碼聲明了一個輔助器,這是在下面為了鎖住資源使用的。出現(xiàn)兩個窗體是因為在程序運行時點擊了兩次Button1。我對Form程序的修改是按照多線程單件模式的代碼事例寫的。  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 08:57 kid_li
@Dflying Chen
單件模式本質(zhì)就是控制對象的構(gòu)建,如果你把對象構(gòu)建的方法給了類的使用者,你就無法控制類對象的構(gòu)建個數(shù),要控制類對象的構(gòu)建個數(shù),就要自己掌握類的構(gòu)建方法,類的構(gòu)建方法不被其他類使用者使用,所以,類的構(gòu)建方法私有化可以達(dá)到限制的目的  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 09:03 kid_li
@bisou.cn
設(shè)計模式是一種思想,他也在不斷的擴展,正像我后面說的對象池,他就可以認(rèn)為是一種單件模式的擴展。我有時間的話會再寫一篇利用單件模式的思想或擴展來實現(xiàn)對象池的代碼。有時間的話,請多多關(guān)注,多提意見  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 09:16 Dflying Chen
@kid_li
您的代碼里還在用form = new Form2();
不也是調(diào)用了公有構(gòu)造函數(shù)??
難道在外面加了幾個lock就是Singleton?
您的例子只能說是您在Form1中以Singleton的方式使用了Form2,而不能說Form2實現(xiàn)了Singleton模式………………
如果真的使用了Singleton,應(yīng)該寫form = Form2.Instance;才對…………  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 12:03 kid_li
@Dflying Chen
設(shè)計模式是思想,而不是固定的代碼片斷,使用設(shè)計模式是為了解決問題,而不是為了使用設(shè)計模式而使用設(shè)計模式。單件模式的實現(xiàn)也不是就我上面寫的那幾種。有很多種寫法。而且這種思想本身也在發(fā)展。就我上面寫的那段WinForm的程序,我不用非要說明這是單件模式,我只想實現(xiàn)我的功能就可以。
TerryLee曾和我說:設(shè)計模式就像打太極拳,要融會貫通,而不是循規(guī)蹈矩,當(dāng)然很高興你跟我討論這個問題,不知這樣的解釋你是否滿意  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 14:54 henry
(我是沒有點出來第二個Form2,如果那位點出來了,給我發(fā)Email,我請她/他在天津的烤鴨)
針對這個功能的情況是沒問題的,因為無論你如何點擊或快速都是基于單線程操作,并沒有出現(xiàn)并發(fā)的情況.
如果樓主沒有修改代碼的情況,那代碼應(yīng)該不是線程安全的.
  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 16:02 bisou.cn
@Terrylee

按照你說的“只有少數(shù)資源比較昂貴的類才會用”的話,我就更不明白了,既然Singleton模式有這么多好處,比如可以減少資源的浪費和代碼輸入量的減少,為什么不只要能用的地方都用呢?這樣不是更好嗎?

望 賜教! 其實就是這個問題我搞不懂,難道這個模式還是有缺點的(當(dāng)然我是指在能用的情況下)  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 16:05 bisou.cn
順便說一下,我看到好多講 Singleton單件模式 的時候 都會用到樓主以上的例子,包括微軟msdn上面的WebCast系列講座,但是每篇發(fā)表出來的blog都有人在下面質(zhì)疑代碼!不知道到底這段代碼有什么問題  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 16:36 Terrylee
@bisou.cn
一下問這么多問題啊,呵呵,我慢慢來解釋吧:)
1.“只有少數(shù)資源比較昂貴的類才會用”比如說NHibernate中的ISession實例,如果說再多線程情況下都去ISession實例的話,開銷會非常之大,所以這里就要使用Singleton模式。
我一再說的是并不是所有的類都要用Singleton模式,比如說實體類,就無法使用。

2.關(guān)于模式的優(yōu)缺點問題,可以說一句,設(shè)計模式是為了靈活性和擴展性、可維護性而存在的,并不是為了提高性能,相反是犧牲了性能來換取靈活性。Singleton模式也有它自身的缺點,實例數(shù)量雖然減少了每次對象請求引用時都要檢查是否存在類的實例,還是需要一些開銷,所以這就是需要一個權(quán)衡的過程!

3.你說的那段代碼是指下面這段嗎?
======================================================
class Singleton
{
private static Singleton _instance;

private Singleton(){}

public static Singleton f_Instance
{
get
{
if(_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
}
====================================================
這段代碼是Single模式的一個簡單實現(xiàn),在單線程下是沒有問題的,但是如果是多線程,就會造成可能創(chuàng)建的實例不是一個,會有并發(fā)操作的問題,更多細(xì)節(jié)可以參考我寫的設(shè)計模式的文章:
http://terrylee.cnblogs.com/archive/2005/12/09/293509.html

4.還有一點,Singleton模式減少代碼輸入量的優(yōu)點從何談起呢?這一點我沒這樣說過,也沒體會到它會減少代碼輸入量。

最后,個人認(rèn)為Singleton模式僅僅是提供了保證類只有一個實例的這樣一種機制!具體使用那種實現(xiàn)方法,根據(jù)具體情況來定。比如說有人說Doubl-Check有缺點,不能使用,但事實上在某些情況下還是可以使用,下面這段代碼出自于Enterprise Library2.0中:
private static object sync = new object();
private static volatile LogWriter writer;
//得到創(chuàng)建LogWriter的工廠實例
private static LogWriterFactory factory = new LogWriterFactory(ConfigurationSourceFactory.Create());

public static LogWriter Writer
{
get
{
if (writer == null)
{
lock (sync)
{
if (writer == null)
{
try
{
//得到LogWriter對象
writer = factory.Create();
}
catch (ConfigurationErrorsException configurationException)
{
TryLogConfigurationFailure(configurationException);

throw;
}
}
}
}
return writer;
}
}  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 17:31 henry
模式本身是沒問題, 但在什么情況下如何實現(xiàn)是存在差別的.
最常見的就是單線程和多線程下的處理,如果對這些問題沒有搞清楚的情況下使用是很危險的.
如果我沒看錯源碼的情況下NHibernate中的ISession應(yīng)該不是采用單件模創(chuàng)建的.
  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 17:42 Terrylee
@henry
暈,可能是我沒有說清楚,NHibernate源碼中的ISession是沒有用Singleton模式,我的意思是在我們自己創(chuàng)建ISession實例時,難道你也不用Singleton模式??
  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-17 18:06 henry
@Terrylee
SessionFactory我往往是采有單件模式保存.
而ISession那看情況來定的,在Win下我通常會采用Singleton模式,但在web下我就不會選擇Singleton模式的.
模式這東西我還是覺得在代碼重構(gòu)過程中掌握會有更多的收益.  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-18 09:13 bisou.cn
@Terrylee

上文上的代碼輸入的減少我是指
不用每個地方都需要Class1 class=new Class1()這樣寫了,后來想想確實沒有代碼量輸入的減少,呵呵

因為我是做web的,基本上都是單線程,不用考慮多線程。所以說如果能用的我覺得都應(yīng)該用。
我想當(dāng)然的覺得“每次對象請求引用時都要檢查是否存在類的實例”,比每次new一個實例應(yīng)該對系統(tǒng)開銷要小的多! 當(dāng)然我是想當(dāng)然的,沒有試驗過 不知道對不對


代碼質(zhì)疑的是 Doubl-Check 這塊,我本以為微軟提供的webcast應(yīng)該不會有什么問題的,呵呵
  回復(fù)  更多評論
  
# re: 設(shè)計模式學(xué)習(xí)筆記(二)——Singleton單件模式 2006-04-18 10:33 Terrylee
@henry,@bisou.cn
從重構(gòu)到模式是最好的使用設(shè)計模式的方法!

我想這個問題的討論該結(jié)束了,再討論下去就會有人說我們無聊了,哈哈:-)

這次的討論很愉快,以后多多交流!
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
博客園 - 探索設(shè)計模式(二):深入淺出單件模式(Sigleton Pattern)
C#設(shè)計模式系列:單件模式(Singleton)
(轉(zhuǎn))C#單例模式詳解
設(shè)計模式之Singleton 單態(tài)模式
從C#的Singleton設(shè)計模式實現(xiàn)看.NET Framework特性對開發(fā)者的重要性
設(shè)計模式——單例模式(Singleton)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服