Franky's LIFE

          Anything... ...

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            53 隨筆 :: 87 文章 :: 6 評論 :: 0 Trackbacks
          這是我寫模式設(shè)計(jì)的第二篇,首先來說說設(shè)計(jì)模式的分類。

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

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

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

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

          下面來說說單件模式:

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

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

          ??????? {

          ??????????? Form2 form = new Form2();

          ??????????? form.Show();

          ??????????? this.Hide();

          ??? }

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

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

          ??????? {

          ??????????? Thread.Sleep(10000);

          ??????????? Form2 form = new Form2();

          ??????????? form.Show();

          ??????????? this.Hide();

          ??? }

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

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

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

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

          在單線程的情況下:私有化構(gòu)造函數(shù),使類的使用者調(diào)用不到這個(gè)構(gòu)造函數(shù)來new一個(gè)實(shí)例。類型中可以自己new一個(gè)實(shí)例。類中創(chuàng)建一個(gè)靜態(tài)私有變量和Static公有屬性。在公有屬性中實(shí)現(xiàn)此類的實(shí)例化。這樣在第一次請求時(shí)創(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(),編譯時(shí)告訴我Singleton()不可訪問(當(dāng)然,人家是私有的,不是自家人當(dāng)然不見)

          這種單線程下的單件模式有幾點(diǎn)要注意:

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

          2、? 不要支持IClinieable接口,因?yàn)闀?dǎo)致多個(gè)對象實(shí)例的出現(xiàn)

          3、? 不能支持序列化

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

          5、? 不能應(yīng)對多線程環(huán)境,因?yàn)闀?dǎo)致多個(gè)對象實(shí)例的出現(xiàn)

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

          class SingletonMuli// 多線程Singleton模式

          ??? {

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

          ??????? private SingletonMuli(){}

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

          ??????? public static SingletonMuli f_Instance

          ??????? {

          ??????????? get

          ??????????? {

          ??????????????? if(_instance == null)

          ??????????????? {

          ??????????????????? lock(lockHelper)

          ??????????????????? {

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

          ??? ??????????????????? {

          ??????????????????????????? _instance = new SingletonMuli();

          ??????????????????????? }

          ??????????????????? }

          ??????????????? }

          ??????????????? return _instance;

          ??????????? }

          ??????? }

          ??? }

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

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

          ??? {

          ??????? public static readonly Singleton1 _instance = new Singleton1();

          ??????? private Singleton1(){}

          ??? }

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

          實(shí)際上面的代碼上相當(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)初始化時(shí)會先執(zhí)行靜態(tài)構(gòu)造器,如果沒有靜態(tài)構(gòu)造函數(shù),系統(tǒng)會默認(rèn)一個(gè)。在訪問此靜態(tài)字段時(shí)執(zhí)行靜態(tài)構(gòu)造器生成。靜態(tài)構(gòu)造器保證了在多線程時(shí)只有一個(gè)線程執(zhí)行,自動加鎖。

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

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

          ??????? private static Form2 form;

          ?

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

          ??????? {

          ??????????? Thread.Sleep(10000);

          ??????? ??? object lockhelp = newobject();

          ??????????? if(form == null)

          ??????????? {

          ??????????????? lock(lockhelp)

          ??????????????? {

          ??????????????????? if(form == null)

          ??????????????????? {

          ??????????????????????? form = new Form2();

          ??????????????????????? form.Show();

          ??????????????????? }

          ??????????????? }

          ??????????? }

          ??????????? this.Hide();

          ??????? }

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

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

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

          posted on 2007-03-19 20:42 Franky 閱讀(107) 評論(0)  編輯  收藏 所屬分類: IT知識
          主站蜘蛛池模板: 华阴市| 逊克县| 屏山县| 莱州市| 醴陵市| 吉林省| 安多县| 开化县| 清原| 望都县| 肇东市| 合山市| 武功县| 南京市| 新昌县| 新沂市| 鄂尔多斯市| 博白县| 长岛县| 石景山区| 阜城县| 宁强县| 衡东县| 宜宾县| 沙洋县| 搜索| 内黄县| 高邑县| 公安县| 安西县| 洪湖市| 内丘县| 建始县| 甘泉县| 宁晋县| 交口县| 屏南县| 衡阳市| 龙州县| 雅安市| 榕江县|