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

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

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

    beauty_beast

    上善若水 厚德載物

    學習設計模式之singleton模式

    Posted on 2005-08-18 21:09 柳隨風 閱讀(541) 評論(1)  編輯  收藏
    本文只是本人的學習總結,目的希望能和大家一起交流分享,順便備忘,如有不正確的地方,歡迎指正。

    singleton模式我們在開發(fā)時經常會使用到,比如將一個系統(tǒng)運行時的初始配置數據封裝成一個配置對象,在系統(tǒng)初始化時實例化該對象,因為對于整個系統(tǒng)運行時該對象的成員都是不變的,如果只需要一個實例就行,這樣對系統(tǒng)的性能是很有益的。往往該配置對象都是和資源密切相關的(例如 數據庫連接、文件等等),但是如果采用該模式設計、編碼不當,常會造成資源泄漏,甚至更嚴重的問題(我的最近一個項目就出現(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;
        }


    }


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

    /*
     * 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

    呵呵,單實例變成三實例了,所以我們編碼、設計時一定要考慮該對象的調用環(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

    這樣就保證了多線程調用時也只有一個實例。
    呵呵,這樣就能保證在同一虛擬機上只有一個實例了嗎?
    如果對象是個可序列化的對象呢?
    /*
     * 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

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














    Feedback

    # re: 學習設計模式之singleton模式  回復  更多評論   

    2005-08-18 22:03 by Rocky
    呵呵,我再補充一點,關于單實例。

    版主例子中給了單實例的一種實現(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(){};
    }

    這種是比較常用的,但有這么一個問題。即該類一旦實例化,那么將永遠不能被回收。即使你將 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)點就是類的實例可以隨時銷毀。但有個缺點:即每次調用都需要創(chuàng)建一個實例出來,有時間上的開銷。

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


    網站導航:
     
    主站蜘蛛池模板: 曰批免费视频播放在线看片二| 九九99热免费最新版| 亚洲国产成+人+综合| 亚洲成av人无码亚洲成av人| 国产精品色拉拉免费看| 亚洲av无码天堂一区二区三区| 亚洲VA成无码人在线观看天堂| 亚洲av乱码一区二区三区| jjizz全部免费看片| 亚洲欧洲自拍拍偷综合| 免费国产草莓视频在线观看黄| 一个人看的www免费视频在线观看| 手机在线看永久av片免费| 久久久久亚洲精品无码网址 | 国产亚洲精品成人AA片| 欧亚精品一区三区免费| 国产午夜亚洲精品国产| 国产成人无码免费视频97 | 老司机永久免费网站在线观看| 永久亚洲成a人片777777| 嫩草在线视频www免费看| 亚洲男人第一av网站| 国产精品色拉拉免费看| 久久精品国产亚洲香蕉| 99热精品在线免费观看| 亚洲另类视频在线观看| 国产免费一区二区三区在线观看| 日韩中文字幕免费| 一区二区视频在线免费观看| 精品国产精品久久一区免费式| 1区1区3区4区产品亚洲| 成人性生交视频免费观看| 免费一级毛片在线播放放视频| 国内大片在线免费看| 亚洲一区综合在线播放| 日韩精品无码区免费专区| 免费在线观看一区| 国产成人涩涩涩视频在线观看免费| 亚洲人成网站色在线观看| 99re6在线精品视频免费播放| 亚洲国产另类久久久精品黑人|