`

设计模式-单例

阅读更多
package com.tag2;
public class 单例模式 {

/**
* 应用场景:
*        1. 系统访问人数
*        2. 系统内部事件
*        3. 系统操作日志
*        4. 系统出错日志
*        5. 系统配置访问接口
*        ...
*        [单例主要应用于一个类只有一个实例]
* 单例模式发展.
*     *. 经典的单例模式
		public class Singleton { 
		  
		   private static Singleton instance = null; [懒汉式]
		  
		   protected Singleton() { 
		      // Exists only to defeat instantiation. 
		   } 
		   public static Singleton getInstance() { 
		      if(instance == null) { 
		         instance = new ClassicSingleton(); 
		      } 
		      return instance; 
		   } 
		}       

     * 点评:这个类只到getInstance()方法被第一次调用时才被创建,但是一般的程序是应用于多线程环境下,这个类线程不安全
     *
		public synchronized static Singleton getInstance() { 
		   if(singleton == null) {  
		      singleton = new Singleton(); 
		   } 
		   logger.info("created singleton: " + singleton); 
		   return singleton; 
		} 

     * 同步方法可以解决线程安全问题,但是同步方法开销会增大,为了整体系统的效率,尽量不要使用同步.
     *
		public  class Singleton {   
		  private static Singleton instance = new Singleton();[饿汉式]       
		}    
		public static Singleton getInstance() {   
		  return Singleton.instance;   
		} 

     * 点评:Bob Lee的写法,在类加载的时候实例就会被创建,只能通过getInstance()接口访问,能够实现线程同步
     *
     * Spring如何实现单例:
     * ApplicationContext context=FileSystemXmlApplicationContext(String configLocation)
     * ApplicationContext context=ClassPathXmlApplicationContext(String configLocation)
     * 这两个都是声名配置文件的,但是加入的是同一个域.
     * public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
...
}
     *  Synchronization monitor for the "refresh" and "destroy"
*  private final Object startupShutdownMonitor = new Object();
*  在对象中声名一个最终对象进行锁定,这样Application一次就只能有一个方法进入.
*  Struts如何实现单例:
		 public static Class applicationClass(String className,
	        ClassLoader classLoader)
	        throws ClassNotFoundException {
	        if (classLoader == null) {
	            // Look up the class loader to be used
	            classLoader = Thread.currentThread().getContextClassLoader();
	
	            if (classLoader == null) {
	                classLoader = RequestUtils.class.getClassLoader();
	            }
	        }
	
	        // Attempt to load the specified class
	        return (classLoader.loadClass(className));
	    }

*  这是Struts得到类加载器并加载一个类.如果类加载器为null则使用当前线程的ClassLoader
*  有人可能会问如果是多线程不是会有问题了吗?我想说的是这是通过类的反映来返回类对象,并不是所有的对象都
*  需要使用多线程支持的,毕竟多线程要处理线程同步,开销太大.
*  现在再来介绍一个Struts如何应用多线程.[Action]
*   <p>Return an <code>Action</code> instance that will be used to process
*   the current request, creating a new one if necessary.</p>
	  protected Action processActionCreate(HttpServletRequest request,
	        HttpServletResponse response, ActionMapping mapping)
	        throws IOException {
	        String className = mapping.getType();
	        Action instance;
	        synchronized (actions) {
	            // Return any existing Action instance of this class
	            instance = (Action) actions.get(className);
	
	            if (instance != null) {
	                if (log.isTraceEnabled()) {
	                    log.trace("  Returning existing Action instance");
	                }
	
	                return (instance);
	            }
	
	            // Create and return a new Action instance
	            if (log.isTraceEnabled()) {
	                log.trace("  Creating new Action instance");
	            }
	
	            try {
	                instance = (Action) RequestUtils.applicationInstance(className);
	
	                // Maybe we should propagate this exception
	                // instead of returning null.
	            } catch (Exception e) {
	                log.error(getInternal().getMessage("actionCreate",
	                        mapping.getPath()), e);
	
	                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
	                    getInternal().getMessage("actionCreate", mapping.getPath()));
	
	                return (null);
	            }
	
	            actions.put(className, instance);
	
	            if (instance.getServlet() == null) {
	                instance.setServlet(this.servlet);
	            }
	        }
	
	        return (instance);
		}      
 
*  点评:actions是一个HashMap实例,这里使用同步代码块的方法synchronized(actions)[注意:同步代码块比同步方法开销小]
*  当一个请求过来时[线程],这里使用了同步,每一次都从actions中得到对象.如果不为空,则返回,如果为空则通过反映生成对象并返回.
*  这其实也属于单例注册.
*  上面介绍了Spring对应多个配置文件时用的同步,Struts的核心Action的同步,下面介绍一个Spring的核心Bean是如何实现单例的.

*  Return the (raw) singleton object registered under the given name,
*  creating and registering a new one if none registered yet.
	 public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
		Assert.notNull(beanName, "'beanName' must not be null");
		synchronized (this.singletonObjects) {
			// Re-check singleton cache within synchronized block.
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);//singletonsCurrentlyInCreation,同步的集合,添加BeanName
				try {
					singletonObject = singletonFactory.getObject();//返回这个对象.
				}
				finally {
					afterSingletonCreation(beanName);//singletonsCurrentlyInCreation.同步的集合中,移除BeanName
				}
				addSingleton(beanName, singletonObject);//添加对象到singletonObjects
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}
	 }
 
* 细心的读者会发现,Struts和Spring都是采用单例注册器的方式实现的.
* private final Map singletonObjects = CollectionFactory.createConcurrentMapIfPossible(16);
* 这里根据你的jdk版本判断使用哪种同步Map
* if  JDKVersion>JAVA_15[或者包括edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap]
*                               new ConcurrentHashMap(initialCapacity)
*                          else
*                               Collections.synchronizedMap(new HashMap(initialCapacity));
* 如果单例注册器中没有此对象
	 *                  1. beforeSingletonCreation(beanName); //监视创建对象前
	 *                  2. singletonObject = singletonFactory.getObject();//返回对象
	 *singletonFactory.getObject();这是接口方法,这个接口由程序在调用的时候实现.

	 *getSingleton(beanName, new ObjectFactory() {
					public Object getObject() throws BeansException {
						try {
							return createBean(beanName, mbd, args);//创建方法就是在子类要重写的
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					}
	  });
	 *                 3.afterSingletonCreation(beanName);//监视创建对象后
	 *                 4.addSingleton(beanName, singletonObject);//添加对象到singletonObjects
	 *                 5.返回该对象.
	 * 综上所述:在应用于系统资源时,为了提供同一接口,需要同步信息,但是Struts和Spring都使用了代码块同步,我们写程序的时候也要向
	 * 那些大师学习,尽量同步代码块.
	 *  
	 */
	 
	
}



分享到:
评论
1 楼 liushuiwuyan 2015-05-07  
[img][/img]

相关推荐

    C++设计模式-单例模式

    李建忠老师的设计模式-单例模式讲解,示例以C++编程语言呈现。

    设计模式-单例模式脑图

    设计模式-单例模式脑图

    Java设计模式-单例模式详解

    Java设计模式-单例模式详解 单例模式是 Java 设计模式中的一种常用的设计模式,旨在保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式的目的是为了保证在一个进程中,某个类有且仅有一个实例。 ...

    ava常用设计模式-单例模式

    ava常用设计模式-单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,有以下特点: 1. 单例类只能有一个实例。 2. 单例类必须自己创建自己的唯一实例。 3. 单例类必须给所有其他对象提供这一...

    一例读懂设计模式-单例模式、简单工厂模式.zip

    本资源“一例读懂设计模式-单例模式、简单工厂模式.zip”旨在帮助初学者通过实例深入理解这两种重要设计模式:单例模式和简单工厂模式。以下是关于这两个模式的详细讲解。 1. **单例模式**: 单例模式是一种限制类...

    常见设计模式-单例模式

    设计模式-单例模式 单例模式是一种常见的设计模式,它的主要作用是确保在内存中仅创建一次对象,并提供一个全局访问点。单例模式有两种类型:饿汉类型和懒汉类型。 饿汉类型的单例模式是在类加载时创建对象,例如...

    PHP5设计模式-单例模式

    单例模式是一种常用的设计模式,它在软件工程中扮演着控制类实例化过程的角色,确保一个类只有一个实例,并提供全局访问点。这种模式在PHP中尤其常见,特别是在需要频繁实例化然后销毁的对象,或者需要控制共享资源...

    java设计模式----单例模式

    在Java编程语言中,设计模式是一种经过验证的解决常见软件设计问题的最佳实践。单例模式是其中最常用的一种,它的核心思想是确保一个类只有一个实例,并提供全局访问点。单例模式的应用场景包括:控制资源的访问、...

    JAVA-设计模式-创建型模式-单例模式

    JAVA-设计模式-创建型模式-单例模式

    设计模式-单例模式

    **设计模式——单例模式** 单例模式是一种广泛应用于软件设计中的创建型设计模式,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。这样做的好处在于控制共享资源的访问,比如线程安全的数据库连接池...

    设计模式-单例设计模式

    ### 设计模式—单例设计模式详解 #### 定义 单例模式是一种常见的创建型设计模式,其核心思想在于确保一个类仅有一个实例存在,并且该实例由该类自行创建,随后向整个系统提供这一唯一实例。 #### 类图解析 在设计...

    android-设计模式-单例模式(干货)

    android 单例模式 干货 告诉你哪种单例模式最实用 最好用 不再迷茫

    iOS 设计模式 -单例

    在iOS开发中,设计模式是解决常见编程问题的模板,为代码组织提供了标准结构。其中,单例模式是一种被广泛...同时,随着Swift的 Combine 框架和轻量级依赖注入的流行,有些情况下可以考虑使用其他设计模式来替代单例。

    java设计模式-单例.pdf

    ### Java设计模式——单例模式详解 #### 一、单例模式概述 单例模式是设计模式中的一个重要组成部分,属于创建型模式之一。其主要作用是确保某个类仅有一个实例存在,并提供一个全局访问该实例的方法。这在很多场景...

    c++设计模式-单例模式

    **单例模式**是软件设计模式中的一种,属于创建型模式。在C++中,单例模式确保一个类只有一个实例,并提供一个全局访问点。这种模式通常用于管理共享资源,如数据库连接、日志系统或者配置文件等。单例模式的主要...

    1.设计模式-单例设计模式1

    单例设计模式是一种常用的设计模式,其主要目的是确保一个类只有一个实例,并提供全局访问点。在Java中,实现单例模式通常有多种方式,包括懒汉模式、饿汉模式、静态内部类以及枚举类型。 1. **懒汉模式**: 懒汉...

    设计模式-单例模式(讲解及其实现代码)

    单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供全局访问点。这种模式在许多场景下非常有用,比如控制共享资源、管理系统级别的对象,如数据库连接池或者线程池等。单例模式的核心在于限制类的...

    通过C++实现设计模式-单例模式.rar

    压缩包代码是一个简单的C++单例模式实现。 在这个例子中,Singleton 类有一个私有的构造函数和一个私有的析构函数,这防止了外部代码直接创建或销毁实例。getInstance 方法是一个静态方法,它返回一个指向 Singleton...

    Java-设计模式-单例模式-实现源码(简单实现、双重检查锁、静态内部类、枚举类)

    单例模式是软件设计模式中的一种经典模式,其主要目的是保证一个类只有一个实例,并提供一个全局访问点。在Java中,有多种实现单例模式的方法,包括简单实现、双重检查锁定(Double-Checked Locking)、静态内部类和...

Global site tag (gtag.js) - Google Analytics