单例设计模式的分析(懒汉,饿汉式)

主要分析的是单例模式。包括懒汉式,饿汉式,登记式,以及懒汉式的改进型,
还有一个关于读取propertoes配置文件的实例。预计分为三节。这是第一节,先分析最简单的懒汉式和饿汉式。

单例模式是设计模式中比较简单的一种。适合于一个类只有一个实例的情况,比如窗口管理器,打印缓冲池和文件系统,
它们都是原型的例子。典型的情况是,那些对象的类型被遍及一个软件系统的不同对象访问,因此需要一个全局的访问
指针,这便是众所周知的单例模式的应用。当然这只有在你确信你不再需要任何多于一个的实例的情况下。 
单例模式的用意在于前一段中所关心的。通过单例模式你可以: 


                     一、确保一个类只有一个实例被建立 
                     二、提供了一个对对象的全局访问指针 
                     三、在不影响单例类的客户端的情况下允许将来有多个实例

经典的单例模式有三种,懒汉式、饿汉式和 登记式。

懒汉式的特点是延迟加载,比如配置文件,采用懒汉式的方法,顾名思义,懒汉么,很懒的,配置文件的实例直到用到的
时候才会加载。。。。。。

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


让我们先看下代码:


懒汉式:

  1. //懒汉式单例模式
  2. public class MySingleton {
  3. //设立静态变量
  4. private static MySingleton mySingleton = null;
  5. private MySingleton(){
  6. //私有化构造函数
  7. System.out.println("-->懒汉式单例模式开始调用构造函数");
  8. }
  9. //开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回
  10. public static MySingleton getInstance(){
  11. System.out.println("-->懒汉式单例模式开始调用公有方法返回实例");
  12. if(mySingleton == null){
  13. System.out.println("-->懒汉式构造函数的实例当前并没有被创建");
  14. mySingleton = new MySingleton();
  15. }else{
  16. System.out.println("-->懒汉式构造函数的实例已经被创建");
  17. }
  18. System.out.println("-->方法调用结束,返回单例");
  19. return mySingleton;
  20. }
  21. }
//懒汉式单例模式
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;
	}
}
看下客户端的测试代码:

  1. public class Client {
  2. /**
  3. * 懒汉式单例模式
  4. * MySingleton
  5. */
  6. public static void myprint(){
  7. System.out.println("-----------------懒汉式单例模式----------------");
  8. System.out.println("第一次取得实例(懒汉式)");
  9. MySingleton s1 = MySingleton.getInstance();
  10. System.out.println("第二次取得实例(懒汉式)");
  11. MySingleton s2 = MySingleton.getInstance();
  12. if(s1==s2){
  13. System.out.println(">>>>>s1,s2为同一实例(懒汉式)<<<<<");
  14. }
  15. System.out.println();
  16. }
  17. /**
  18. * @param args
  19. */
  20. public static void main(String[] args) {
  21. // TODO Auto-generated method stub
  22. //懒汉式
  23. myprint();
  24. //饿汉式
  25. //myprint2();
  26. //懒汉式改进
  27. //myprint2a();
  28. //登记式
  29. //myprint3();
  30. }
  31. }
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为同一实例(懒汉式)<<<<<


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



饿汉式

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

	//设立静态变量,直接创建实例
	private static MySingleton2 mySingleton = new MySingleton2();

	private MySingleton2(){
		//私有化构造函数
		System.out.println("-->饿汉式单例模式开始调用构造函数");
	}
	
	//开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回
	public static MySingleton2 getInstance(){
		System.out.println("-->饿汉式单例模式开始调用公有方法返回实例");
		return mySingleton;
	}
}

看下客户端的测试代码:

  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. }
	/**
	 * 饿汉式单例模式
	 * 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();
	}
  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. }
	/**
	 * @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进行控制,那么就会有两个实例被创建。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值