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

目 录CONTENT

文章目录

单例模式(Singleton Pattern)

Dettan
2021-04-10 / 0 评论 / 0 点赞 / 154 阅读 / 855 字
温馨提示:
本文最后更新于 2022-07-23,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
要求
写一个类, 它只能有一个实例, 既多次声明这个类拿到的都是同一个东西. 要求这个功能的代码只在这个类里.
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 synchronized 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定义判断,此判断依据通常来自于组件配置文件的单例属性开关  
		    //<bean id="date" class="java.util.Date" scope="singleton"/>  
		    //如果是单例,做如下处理  
		    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实例  
		   //<bean id="date" class="java.util.Date" scope="prototype"/>  
		   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("./src/sqlMapConfig.xml"))).openSession();

        public sql() throws FileNotFoundException {
        }
    }
}

0

评论区