首页 > 代码库 > [转]设计模式--单例模式(一)懒汉式和饿汉式
[转]设计模式--单例模式(一)懒汉式和饿汉式
饿汉式的特点是一开始就加载了,如果说懒汉式是“时间换空间”,那么饿汉式就是“空间换时间”,因为一开始就创建了实例,所以每次用到的之后直接返回就好了。
让我们先看下代码:
懒汉式:
//懒汉式单例模式
//懒汉式单例模式 public class MySingleton { //设立静态变量 private static MySingleton mySingleton = null; private MySingleton(){ //私有化构造函数 System.out.println("-->懒汉式单例模式开始调用构造函数"); } //开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回 public static MySingleton getInstance(){ System.out.println("-->懒汉式单例模式开始调用公有方法返回实例"); if(mySingleton == null){ System.out.println("-->懒汉式构造函数的实例当前并没有被创建"); mySingleton = new MySingleton(); }else{ System.out.println("-->懒汉式构造函数的实例已经被创建"); } System.out.println("-->方法调用结束,返回单例"); return mySingleton; } }看下客户端的测试代码:
public class Client { /** * 懒汉式单例模式 * MySingleton */ public static void myprint(){ System.out.println("-----------------懒汉式单例模式----------------"); System.out.println("第一次取得实例(懒汉式)"); MySingleton s1 = MySingleton.getInstance(); System.out.println("第二次取得实例(懒汉式)"); MySingleton s2 = MySingleton.getInstance(); if(s1==s2){ System.out.println(">>>>>s1,s2为同一实例(懒汉式)<<<<<"); } System.out.println(); } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub //懒汉式 myprint(); //饿汉式 //myprint2(); //懒汉式改进 //myprint2a(); //登记式 //myprint3(); } }输出结果为:
-----------------懒汉式单例模式---------------- 第一次取得实例(懒汉式),懒汉式单例模式开始调用公有方法返回实例, 懒汉式构造函数的实例当前并没有被创建懒汉式单例模式开始调用构造函数 ,方法调用结束,返回单例 第二次取得实例(懒汉式) ,懒汉式单例模式开始调用公有方法返回实例 ,懒汉式构造函数的实例已经被创建 ,方法调用结束,返回单例 s1,s2为同一实例(懒汉式)
可以看出,在第一次调用公有方法的时候,并没有实例,所以我们创建了一个实例,之后再访问的时候,因为已经有一个已经创建好的实例,所以直接返回了。
饿汉式:
- //饿汉式单例模式
- public class MySingleton2 {
- //设立静态变量,直接创建实例
- private static MySingleton2 mySingleton = new MySingleton2();
- private MySingleton2(){
- //私有化构造函数
- System.out.println("-->饿汉式单例模式开始调用构造函数");
- }
- //开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回
- public static MySingleton2 getInstance(){
- System.out.println("-->饿汉式单例模式开始调用公有方法返回实例");
- return mySingleton;
- }
- }
//饿汉式单例模式 public class MySingleton2 { //设立静态变量,直接创建实例 private static MySingleton2 mySingleton = new MySingleton2(); private MySingleton2(){ //私有化构造函数 System.out.println("-->饿汉式单例模式开始调用构造函数"); } //开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回 public static MySingleton2 getInstance(){ System.out.println("-->饿汉式单例模式开始调用公有方法返回实例"); return mySingleton; } }看下客户端的测试代码:
/** * 饿汉式单例模式 * MySingleton2 */ public static void myprint2(){ System.out.println("-----------------饿汉式单例模式----------------"); System.out.println("第一次取得实例(饿汉式)"); MySingleton2 s1 = MySingleton2.getInstance(); System.out.println("第二次取得实例(饿汉式)"); MySingleton2 s2 = MySingleton2.getInstance(); if(s1==s2){ System.out.println(">>>>>s1,s2为同一实例(饿汉式)<<<<<"); } System.out.println(); }
/** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub //懒汉式 //myprint(); //饿汉式 myprint2(); //懒汉式改进 //myprint2a(); //登记式 //myprint3(); }
输出结果为:
-----------------饿汉式单例模式---------------- 第一次取得实例(饿汉式) -->饿汉式单例模式开始调用构造函数 -->饿汉式单例模式开始调用公有方法返回实例 第二次取得实例(饿汉式) -->饿汉式单例模式开始调用公有方法返回实例 >>>>>s1,s2为同一实例(饿汉式)<<<<<
总结一下,两种方案的构造函数和公用方法都是静态的(static),实例和公用方法又都是私有的(private)。但是饿汉式每次调用的时候不用做创建,直接返回已经创建好的实例。这样虽然节省了时间,但是却占用了空间,实例本身为static的,会一直在内存中带着。懒汉式则是判断,在用的时候才加载,会影响程序的速度。最关键的是,在并发的情况下,懒汉式是不安全的。如果两个线程,我们称它们为线程1和线程2,在同一时间调用getInstance()方法,如果线程1先进入if块,然后线程2进行控制,那么就会有两个实例被创建。
[转]设计模式--单例模式(一)懒汉式和饿汉式