zoukankan      html  css  js  c++  java
  • 公用技术——设计模式1——创建型模式——单例模式

    1、概念

      单例模式是为了保证在一个JVM中类的实例只存在一个。这样做的目的是:

    1. 某些对象的生命周期很短,每次都创建会造成内存的浪费,例如Integer。
    2. 某些对象,存在第二个实例时属于一种逻辑错误,例如Spring的applicationContext,Servlet的ServletContext等等。
    3. 某些对象由于它的职责比较单一,存在第二个没有任何意义,例如工厂类。

      它的解决方案是:

    • 不允许创建其他对象,所以必须是私有的构造器
    • 必须存在一个public方法,它的返回值是当前对象的实例。

    2、UML图

    3、代码

    3.1 懒汉式

    普通场景下有两种实现方案,第一种实现方案称为懒汉式。

    public Class SingletonExample{
    	private static SingletonExample example;
    	// 私有的构造器
    	private SingletonExample()
    	{
    	}
    	
    	/**
    	 * 
    	 * @Title: getInstance  
    	 * @Description: 公共的访问实例对象的方法,必须使用static   
    	 * @return 实例对象
    	 */
    	public static SingletonExample getInstance()
    	{
    		if(example == null)
    		{
    			return new SingletonExample();
    		}
    		return example;
    	}
    }

    3.2 恶汉式

    public class SingletonExample {
    	private static SingletonExample example = new SingletonExample();
    	// 私有的构造器
    	private SingletonExample(){
    	}
    	
    	/**
    	 * 
    	 * @Title: getInstance  
    	 * @Description: 公共的访问实例的方法 
    	 * @return 实例对象
    	 */
    	public static SingletonExample getInstance(){
    		return example;
    	}
    }
    

      两种方式比较:懒汉式在定义成员变量时没有进行初始化,在getInstance方法中添加了非NULL判断,而恶汉式在定义成员变量时直接初始化。在getInstance方法中直接返回实例对象。

    4、讨论

      问题1:如何确保多线程环境下只有一个实例?

      答:为了保证在多线程情况下只有一个实例对象,需要使用synchronize关键字进行加锁,第一种实现方式是在getInstance方法上加锁,另外一种实现方式是在Class文件上加锁。在getInstance方法中如果包含其他逻辑代码,会导致整个程序非常缓慢,所以第二种方案拥有更好的性能。

      第一种方式,在方法上添加锁。

    public static synchronized SingletonExample getInstance(){}
    

      第二种方式,在Class文件上添加锁

    public static SingletonExample getInstance()
    {
    	if(example == null)
    	{
    		synchronized(SingletonExample.class)
    		{
    			return new SingletonExample();
    		}
    	}
    	return example;
    }

        问题2:如何保证多个类加载器,多个JVM下只有一个实例?

        答:当拥有多个类加载器时,每个类加载器拥有该对象的一个实例,不存在多个类加载器拥有同一个实例对象的情形。       多个JVM下必定存在不同的实例。

        问题3: 懒汉式与恶汉式有什么区别?

      答:从代码中可以看到恶汉式提前创建了对象,如果创建对象的过程很耗性能或者是创建对象需要一些耗时的操作,此时建议使用赖汉式,即需要该对象时在创建。如果对象本身不那么复杂,我们日常启动tomcat时会加载成千上万个类,多创建几个对象也没有多大影响,例如加载工厂类,创建Integer这类型的对象,此时建议使用恶汉式,提前加载。

      衡量懒汉与恶汉的区别,以及是否使用sync关键字,都是考虑到创建对象是否会影响性能,如果确定不影响,建议使用恶汉式。会影响,建议使用懒汉式。

    5、示例

    1. 第一类问题,对象生命周期短,反复创建会浪费内存的情形,可以参考Integer类。
    2. 第二类问题,存在多个实例时是一种逻辑错误,可以参考在一个request请求线程中,出现相同Servlet的多个实例。
    3. 第三类问题,多个实例没有任何意义,对象的职责比较单一,这类型很常见,例如工厂类。
  • 相关阅读:
    android基于adb的性能测试
    mysql-3 数据表的创建、增删改查
    17.3.16---python内建函数
    17.3.15---C语言详解FILE文件操作
    17.3.15---关于GPIO控制流水灯的信息
    17.3.15---关于GPIO学习笔记
    17.3.14--对于时钟的知识,涉及到的总结
    17.3.14对于面向对象的理解
    17.3.13--pycharm2和3的常识问题
    17.3.13--python编码问题
  • 原文地址:https://www.cnblogs.com/rain144576/p/12330105.html
Copyright © 2011-2022 走看看