zoukankan      html  css  js  c++  java
  • 设计模式--单例模式(一)懒汉式和饿汉式

    设计模式--单例模式(一)懒汉式和饿汉式

    原创 2012年08月29日 16:28:43
    本文是设计模式学习笔记的第二篇文章,主要分析的是单例模式。包括懒汉式,饿汉式,登记式,以及懒汉式的改进型,
    还有一个关于读取propertoes配置文件的实例。预计分为三节。这是第一节,先分析最简单的懒汉式和饿汉式。
    
    单例模式是设计模式中比较简单的一种。适合于一个类只有一个实例的情况,比如窗口管理器,打印缓冲池和文件系统,
    它们都是原型的例子。典型的情况是,那些对象的类型被遍及一个软件系统的不同对象访问,因此需要一个全局的访问
    指针,这便是众所周知的单例模式的应用。当然这只有在你确信你不再需要任何多于一个的实例的情况下。 
    单例模式的用意在于前一段中所关心的。通过单例模式你可以: 
    
    
                         一、确保一个类只有一个实例被建立 
                         二、提供了一个对对象的全局访问指针 
                         三、在不影响单例类的客户端的情况下允许将来有多个实例
    
    经典的单例模式有三种,懒汉式、饿汉式和 登记式。
    
    懒汉式的特点是延迟加载,比如配置文件,采用懒汉式的方法,顾名思义,懒汉么,很懒的,配置文件的实例直到用到的
    时候才会加载。。。。。。
    

    饿汉式的特点是一开始就加载了,如果说懒汉式是“时间换空间”,那么饿汉式就是“空间换时间”,因为一开始就创建了实例,所以每次用到的之后直接返回就好了。

    让我们先看下代码:

    懒汉式:

    [java] view plain copy
     
    1. //懒汉式单例模式  
    2. public class MySingleton {  
    3.   
    4.     //设立静态变量  
    5.     private static MySingleton mySingleton = null;  
    6.   
    7.     private MySingleton(){  
    8.         //私有化构造函数  
    9.         System.out.println("-->懒汉式单例模式开始调用构造函数");  
    10.     }  
    11.       
    12.     //开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回  
    13.     public static MySingleton getInstance(){  
    14.         System.out.println("-->懒汉式单例模式开始调用公有方法返回实例");  
    15.         if(mySingleton == null){  
    16.             System.out.println("-->懒汉式构造函数的实例当前并没有被创建");  
    17.             mySingleton = new MySingleton();  
    18.         }else{  
    19.             System.out.println("-->懒汉式构造函数的实例已经被创建");  
    20.         }  
    21.         System.out.println("-->方法调用结束,返回单例");  
    22.         return mySingleton;  
    23.     }  
    24. }  
    看下客户端的测试代码:
    [java] view plain copy
     
    1. public class Client {  
    2.       
    3.     /** 
    4.      * 懒汉式单例模式 
    5.      * MySingleton 
    6.      */  
    7.     public static void myprint(){  
    8.         System.out.println("-----------------懒汉式单例模式----------------");  
    9.         System.out.println("第一次取得实例(懒汉式)");  
    10.         MySingleton s1 = MySingleton.getInstance();  
    11.         System.out.println("第二次取得实例(懒汉式)");  
    12.         MySingleton s2 = MySingleton.getInstance();  
    13.         if(s1==s2){  
    14.             System.out.println(">>>>>s1,s2为同一实例(懒汉式)<<<<<");  
    15.         }  
    16.         System.out.println();  
    17.     }  
    18.         /** 
    19.      * @param args 
    20.      */  
    21.     public static void main(String[] args) {  
    22.         // TODO Auto-generated method stub  
    23.         //懒汉式  
    24.         myprint();  
    25.         //饿汉式  
    26.         //myprint2();  
    27.         //懒汉式改进  
    28.         //myprint2a();  
    29.         //登记式  
    30.         //myprint3();  
    31.   
    32.     }  
    33.   
    34. }  

    输出结果为:

    -----------------懒汉式单例模式----------------
    第一次取得实例(懒汉式)
    -->懒汉式单例模式开始调用公有方法返回实例
    -->懒汉式构造函数的实例当前并没有被创建
    -->懒汉式单例模式开始调用构造函数
    -->方法调用结束,返回单例
    第二次取得实例(懒汉式)
    -->懒汉式单例模式开始调用公有方法返回实例
    -->懒汉式构造函数的实例已经被创建
    -->方法调用结束,返回单例
    >>>>>s1,s2为同一实例(懒汉式)<<<<<

    可以看出,在第一次调用公有方法的时候,并没有实例,所以我们创建了一个实例,之后再访问的时候,因为已经有一个已经创建好的实例,所以直接返回了。

    饿汉式:

    [java] view plain copy
     
    1. //饿汉式单例模式  
    2. public class MySingleton2 {  
    3.   
    4.     //设立静态变量,直接创建实例  
    5.     private static MySingleton2 mySingleton = new MySingleton2();  
    6.   
    7.     private MySingleton2(){  
    8.         //私有化构造函数  
    9.         System.out.println("-->饿汉式单例模式开始调用构造函数");  
    10.     }  
    11.       
    12.     //开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回  
    13.     public static MySingleton2 getInstance(){  
    14.         System.out.println("-->饿汉式单例模式开始调用公有方法返回实例");  
    15.         return mySingleton;  
    16.     }  
    17. }  

    看下客户端的测试代码:
    [java] view plain copy
     
    1. /** 
    2.  * 饿汉式单例模式 
    3.  * MySingleton2 
    4.  */  
    5. public static void myprint2(){  
    6.     System.out.println("-----------------饿汉式单例模式----------------");  
    7.     System.out.println("第一次取得实例(饿汉式)");  
    8.     MySingleton2 s1 = MySingleton2.getInstance();  
    9.     System.out.println("第二次取得实例(饿汉式)");  
    10.     MySingleton2 s2 = MySingleton2.getInstance();  
    11.     if(s1==s2){  
    12.         System.out.println(">>>>>s1,s2为同一实例(饿汉式)<<<<<");  
    13.     }  
    14.     System.out.println();  
    15. }  
    [java] view plain copy
     
    1. /** 
    2.  * @param args 
    3.  */  
    4. public static void main(String[] args) {  
    5.     // TODO Auto-generated method stub  
    6.     //懒汉式  
    7.     //myprint();  
    8.     //饿汉式  
    9.     myprint2();  
    10.     //懒汉式改进  
    11.     //myprint2a();  
    12.     //登记式  
    13.     //myprint3();  
    14.   
    15. }  

    输出结果为:

    -----------------饿汉式单例模式----------------
    第一次取得实例(饿汉式)
    -->饿汉式单例模式开始调用构造函数
    -->饿汉式单例模式开始调用公有方法返回实例
    第二次取得实例(饿汉式)
    -->饿汉式单例模式开始调用公有方法返回实例
    >>>>>s1,s2为同一实例(饿汉式)<<<<<

    总结一下,两种方案的构造函数和公用方法都是静态的(static),实例和公用方法又都是私有的(private)。但是饿汉式每次调用的时候不用做创建,直接返回已经创建好的实例。这样虽然节省了时间,但是却占用了空间,实例本身为static的,会一直在内存中带着。懒汉式则是判断,在用的时候才加载,会影响程序的速度。最关键的是,在并发的情况下,懒汉式是不安全的。如果两个线程,我们称它们为线程1和线程2,在同一时间调用getInstance()方法,如果线程1先进入if块,然后线程2进行控制,那么就会有两个实例被创建。

  • 相关阅读:
    node.js 入门笔记3
    Linux常用命令大全(非常全!!!)
    数据库导入导出命令(结构+数据)?
    列举 创建索引但是无法命中索引的8种情况。
    简述触发器、函数、视图、存储过程?
    什么是事务?MySQL如何支持事务?
    简述数据库三大范式
    MySQL常见数据库引擎及比较?
    列举常见的关系型数据库和非关系型都有那些?
    操作系统常见面试题
  • 原文地址:https://www.cnblogs.com/muliu/p/8176150.html
Copyright © 2011-2022 走看看