侧边栏壁纸
  • 累计撰写 781 篇文章
  • 累计创建 1 个标签
  • 累计收到 1 条评论
标签搜索

单例模式(Singleton Pattern)

Dettan
2021-04-10 / 0 评论 / 0 点赞 / 90 阅读 / 3,572 字
温馨提示:
本文最后更新于 2022-04-30,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
要求
写一个类, 它只能有一个实例, 既多次声明这个类拿到的都是同一个东西. 要求这个功能的代码只在这个类里.
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例
实现
1.
DCL (双锁检测)
spring 就是用的这种, 这种是多语言通用的, 线程安全 .
public class Singleton{
	private static volatile Singleton instance;
public static Singleton getInstance(){
	if(instance == null){
		synchronized(Singleton.class){
			if(instance == null){
				instance = new Singleton();
			}
		}
	}
	return instance;
}

private Singleton(){}

}

2.
initialization on demand holder idiom
只能是static, 优点是简洁
public class instaceFactory{
	private class holder{
		public static Instance instance = new Instance();
	}
public static Instance getInstance(){
	return holer.instance;
}

}

3.
懒汉模式
不会从开头就浪费内存,但是因为是同步方法所以性能低.
public class SingleClass{
		private static SingleClass instance;
	private SingleClass(){}
	
	public <span style="background:rgb(251,228,228);">synchronized</span> static SingleClass newInstance(){
			if (instace == null)
					instance =  = new SingleClass();
			
			return instance;
	}

}

4.
饿汉模式
public class SingleClass{
		private static SingleClass instance = new SingleClass();
	private SingleClass(){}
	
	public static SingleClass newInstance(){
					return instance;
	}

}

5.
单例注册表 (Spring 使用)
Import java.util.HashMap;  

Public class RegSingleton{
Static private HashMap registry=new HashMap();

	//静态块,在类被加载时自动执行  
	Static{  
			RegSingleton rs=new RegSingleton();  
			Registry.put(rs.getClass().getName(),rs);  
	}  

	//受保护的默认构造函数,如果为继承关系,则可以调用,克服了单例类不能为继承的缺点  
	Protected RegSingleton(){}  

	//静态工厂方法,返回此类的唯一实例  
	public static RegSingleton getInstance(String name){  
			if(name==null)
					name=” RegSingleton”;  

			if(registry.get(name)==null){  
					try{  
							registry.put(name,Class.forName(name).newInstance());  
					}Catch(Exception ex){ex.printStackTrace();}  
			}  
			Return (RegSingleton)registry.get(name);  
	}  

}




public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{  
		// 充当了Bean实例的缓存,实现方式和单例注册表相同 
	private final Map singletonCache=new HashMap(); 

	public Object getBean(String name)throws BeansException{  
	   return getBean(name,null,null);  
	} 
	...  
	public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{  
	  //对传入的Bean name稍做处理,防止传入的Bean name名有非法字符(或则做转码)  
	  String beanName=transformedBeanName(name);  
	  Object bean=null;  
	  //手工检测单例注册表  
	  Object sharedInstance=null;  
	  //使用了代码锁定同步块,原理和同步方法相似,但是这种写法效率更高  
	  synchronized(this.singletonCache){  
	     sharedInstance=this.singletonCache.get(beanName);  
	   }  
	  if(sharedInstance!=null){  
	     ...  
	     //返回合适的缓存Bean实例  
	     bean=getObjectForSharedInstance(name,sharedInstance);  
	  }else{  
	    ...  
	    //取得Bean的定义  
	    RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);  
	     ...  
	    //根据Bean定义判断,此判断依据通常来自于组件配置文件的单例属性开关  
	    //&lt;bean id=&quot;date&quot; class=&quot;java.util.Date&quot; scope=&quot;singleton&quot;/&gt;  
	    //如果是单例,做如下处理  
	    if(mergedBeanDefinition.isSingleton()){  
	       synchronized(this.singletonCache){  
	        //再次检测单例注册表  
	         sharedInstance=this.singletonCache.get(beanName);  
	         if(sharedInstance==null){  
	            ...  
	           try {  
	              //真正创建Bean实例  ,这里在多例模式里直接就能用了,为什么还要再来一步.
	              sharedInstance=createBean(beanName,mergedBeanDefinition,args);  
	              //向单例注册表注册Bean实例  
	               addSingleton(beanName,sharedInstance);  
	           }catch (Exception ex) {  
	              ...  
	           }finally{  
	              ...  
	          }  
	         }  
	       }  
	      bean=getObjectForSharedInstance(name,sharedInstance);  
	    }  
	   //如果是非单例,即prototpye,每次都要新创建一个Bean实例  
	   //&lt;bean id=&quot;date&quot; class=&quot;java.util.Date&quot; scope=&quot;prototype&quot;/&gt;  
	   else{  
	      bean=createBean(beanName,mergedBeanDefinition,args);  
	   }  
	}  
	...  
	return bean;  
	}  

}




例子
public class MySqlSessionFactory {
    private MySqlSessionFactory() {//构造函数私有化
    }
public static SqlSession getSqlSession() throws FileNotFoundException {
    return new sql().sqlSession;
}

	//利用内部类只有在使用的时候才加载的原理来延迟加载。
public static class sql {
    public SqlSession sqlSession = (new SqlSessionFactoryBuilder().build(new FileReader(&quot;./src/sqlMapConfig.xml&quot;))).openSession();

    public sql() throws FileNotFoundException {
    }
}

}




0

评论区