<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    beauty_beast

    上善若水 厚德載物
    本文只是本人的學(xué)習(xí)總結(jié),目的希望能和大家一起交流分享,順便備忘,如有不正確的地方,歡迎指正。

    singleton模式我們在開發(fā)時經(jīng)常會使用到,比如將一個系統(tǒng)運行時的初始配置數(shù)據(jù)封裝成一個配置對象,在系統(tǒng)初始化時實例化該對象,因為對于整個系統(tǒng)運行時該對象的成員都是不變的,如果只需要一個實例就行,這樣對系統(tǒng)的性能是很有益的。往往該配置對象都是和資源密切相關(guān)的(例如 數(shù)據(jù)庫連接、文件等等),但是如果采用該模式設(shè)計、編碼不當(dāng),常會造成資源泄漏,甚至更嚴(yán)重的問題(我的最近一個項目就出現(xiàn)過問題)。
    一個簡單的單實例模式實現(xiàn)如下:
    /*
     * Created on 2005-8-18
     *
     * TODO To change the template for this generated file go to
     * Window - Preferences - Java - Code Style - Code Templates
     
    */

    package study.design.singleton;



    /**
     * @author liusuifeng
     * 
     * TODO To change the template for this generated type comment go to Window -
     * Preferences - Java - Code Style - Code Templates
     
    */

    public class TestSingleTon   {
        
    private static TestSingleTon test = null;

        
    private TestSingleTon() {

            System.
    out.println("contructor has been inited");
        }


        
    public static synchronized TestSingleTon getInstance() {
            
    if (test == null{

                test 
    = new TestSingleTon();

            }

            
    return test;
        }


    }


    這樣的定義在單線程應(yīng)用中時沒有問題的,但是如果是多線程訪問的話實際就不是單實例了:
    舉個簡單例子:

    /*
     * Created on 2005-8-18
     *
     * TODO To change the template for this generated file go to
     * Window - Preferences - Java - Code Style - Code Templates
     
    */
    package study.design.singleton;

    /**
     * @author liusuifeng
     
     
    */
    public class TestThread extends Thread {
        
    public void run(){
            TestSingleTon test
    =TestSingleTon.getInstance();        
            System.
    out.println("TestSingleTon===="+test);
            
        }
        
        
    public static void main(String[] args){
            
    for(int i=0;i<10;i++){
                TestThread mthread
    =new TestThread();                
                mthread.start();
            }        
        }
        
        
    }


    運行時系統(tǒng)輸出如下:
    TestSingleTon====study.design.singleton.TestSingleTon@107077e
    TestSingleTon====study.design.singleton.TestSingleTon@7ced01
    TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
    TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
    TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
    TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
    TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
    TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
    TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8

    呵呵,單實例變成三實例了,所以我們編碼、設(shè)計時一定要考慮該對象的調(diào)用環(huán)境,保險起見,我們可以加上同步,修改原來的實現(xiàn),將方法加上同步:
    public static synchronized TestSingleTon getInstance() {
            
    if (test == null{

                test 
    = new TestSingleTon();

            }

            
    return test;
        }

    執(zhí)行測試代碼輸出:
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a
    TestSingleTon====study.design.singleton.TestSingleTon@11a698a

    這樣就保證了多線程調(diào)用時也只有一個實例。
    呵呵,這樣就能保證在同一虛擬機(jī)上只有一個實例了嗎?
    如果對象是個可序列化的對象呢?
    /*
     * Created on 2005-8-18
     *
     * TODO To change the template for this generated file go to
     * Window - Preferences - Java - Code Style - Code Templates
     
    */
    package study.design.singleton;


    import java.io.Serializable;

    /**
     * @author liusuifeng
     * 
     * TODO To change the template for this generated type comment go to Window -
     * Preferences - Java - Code Style - Code Templates
     
    */
    public class TestSingleTon implements Serializable {
        
    private static TestSingleTon test = null;

        
    private TestSingleTon() {

            System.
    out.println("contructor has been inited");
        }

        
    public static synchronized TestSingleTon getInstance() {
            
    if (test == null) {

                test 
    = new TestSingleTon();

            }
            
    return test;
        }

    }

    下面的方法就又偷出一個實例出來:
    /*
     * Created on 2005-8-18
     *
     * TODO To change the template for this generated file go to
     * Window - Preferences - Java - Code Style - Code Templates
     
    */
    package study.design.singleton;

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;

    /**
     * @author liusuifeng
     * 
     * TODO To change the template for this generated type comment go to Window -
     * Preferences - Java - Code Style - Code Templates
     
    */
    public class TestSerialObject {
        
        
    private void writeObject() {
            TestSingleTon tempobj 
    = TestSingleTon.getInstance();
            ObjectOutputStream oos
    =null;
            
    try {
                oos 
    = new ObjectOutputStream(
                        
    new FileOutputStream("c:\\object.data"));
                oos.writeObject(tempobj);
            } 
    catch (FileNotFoundException e1) {
                
                e1.printStackTrace();
            } 
    catch (IOException e1) {            
                e1.printStackTrace();
            }
            
    finally{
                
    try {
                    oos.close();
                } 
    catch (IOException e) {
                    
                    e.printStackTrace();
                }
            }

        }

        
    public Object getSerialObject() {
            Object o 
    = new Object();
            ObjectInputStream ois 
    =null;
            writeObject();
            
    try {
                 ois 
    = new ObjectInputStream(new FileInputStream(
                        
    "c:\\object.data"));
                 o
    =ois.readObject();
                
            } 
    catch (FileNotFoundException e) {            
                e.printStackTrace();
            } 
    catch (IOException e) {
                
                e.printStackTrace();
            } 
    catch (ClassNotFoundException e) {
                
                e.printStackTrace();
            }
            
    finally{
                
    try {
                    ois.close();
                } 
    catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            
    return o;
        }

        
    public static void main(String[] args) {
            TestSerialObject to
    =new TestSerialObject();            
            Object obj1
    =to.getSerialObject();
            System.
    out.println(obj1.equals(TestSingleTon.getInstance()));
        }
    }

    運行輸出如下:
    contructor has been inited
    false

    學(xué)習(xí)總結(jié)如下:
        采用單實例模式時設(shè)計編碼時要盡可能的多考慮其調(diào)用場景,在實現(xiàn)中規(guī)避不應(yīng)該出現(xiàn)的多實例情形。














    Feedback

    # re: 學(xué)習(xí)設(shè)計模式之singleton模式  回復(fù)  更多評論   

    2005-08-18 22:03 by Rocky
    呵呵,我再補(bǔ)充一點,關(guān)于單實例。

    版主例子中給了單實例的一種實現(xiàn):
    public class TestClass
    {
    private static TestClass instance;
    private TestClass(){}

    public static TestClass()
    {
    if( null != instance) instance = new TestClass();
    return instance;
    }
    public void testA(){};
    public void testB(){};
    }

    這種是比較常用的,但有這么一個問題。即該類一旦實例化,那么將永遠(yuǎn)不能被回收。即使你將 instance 賦成 null,也不能將該類清除掉。


    還有一種單實例模式,見下:
    public class TestClass
    {
    private String aaa;
    public TestClass(){
    //初始化單實例中的一些變量
    aaa = .....;
    }

    public static void testA(){
    //針對aaa的操作
    }

    public static void testB(){}{
    //針對aaa的操作
    }
    }
    即將方法聲明為 static 方法。這樣聲明之后,那么針對aaa的操作的所有行為也將遵循單實例模式。

    這種方式的優(yōu)點就是類的實例可以隨時銷毀。但有個缺點:即每次調(diào)用都需要創(chuàng)建一個實例出來,有時間上的開銷。

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 婷婷精品国产亚洲AV麻豆不片| 免费一级毛片不卡在线播放| 亚洲开心婷婷中文字幕| a级毛片免费观看网站| 亚洲第一区精品观看| 一区二区免费电影| 国产性爱在线观看亚洲黄色一级片 | 亚洲免费日韩无码系列| 国产免费观看青青草原网站| 亚洲精品动漫免费二区| 国产成人免费片在线观看| 国产偷国产偷亚洲高清人| 亚洲精品专区在线观看| a级片免费在线观看| 亚洲国产二区三区久久| 国产精品久久永久免费| 国产成人亚洲综合网站不卡| 国产精品免费综合一区视频| 免费福利资源站在线视频| 中文字幕不卡亚洲| 日本在线看片免费人成视频1000| 亚洲天堂视频在线观看| 成年丰满熟妇午夜免费视频| 真正全免费视频a毛片| 亚洲乱亚洲乱妇无码麻豆| 18女人水真多免费高清毛片| 亚洲日韩av无码中文| 亚洲国产主播精品极品网红| 女同免费毛片在线播放| 亚洲娇小性xxxx| 亚洲综合另类小说色区色噜噜| 免费h视频在线观看| 亚洲日韩中文字幕一区| 狠狠亚洲狠狠欧洲2019| 天天影院成人免费观看| 色婷婷亚洲一区二区三区| 久久亚洲成a人片| 天天操夜夜操免费视频| 中文字幕免费人成乱码中国| 亚洲欧洲日产韩国在线| 成人亚洲综合天堂|