狂啃单例设计模式

什么是单例设计模式?

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

类结构图

在这里插入图片描述
具体实现
需要:
(1)将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
(2)在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型。
(3)定义一个静态方法返回这个唯一对象。

单例模式的几种实现方式

饿汉模式/立即加载
  饿汉模式就是在类的初始化的时候已经将对象创建完毕,不管对象是不是立刻会用到,所以称之为饿汉式。
public class Singleton{
	//构造方法私有化
	private Singleton(){};

	//将自身实例对象设置为一个属性,并用static,final修饰(final修饰保证它是不会被改变的,)
	private static final Singleton instance = new Singleton();
	
	//静态方法返回实例
	public static Singleton getInstance(){
		return instance;
	} 
}
“饿汉模式”的优缺点:
优点:实现起来简单,在多线程中不会出现线程安全问题。
缺点:当类被初始换的时候,会初始化static的instance,静态变量被创建并被分配内存空间,无论是否使用这个实例,直到jvm回收该类之前,静态变量都存在于内存中,因此在某些特定时间下会浪费内存。
方式二:懒汉模式/延迟加载
  懒汉模式就是为了优化饿汉式带来的内存浪费,当需要创建对象时才创建。
public class Singleton{
	//构造方法私有化
	private Singleton(){};

	// 将自身实例化对象设置为一个属性,并用static修饰
	private static Singleton instance;
	
	//静态方法返回实例
	public static Singleton getInstance(){
		if(instance == null){
			instance = new Singleton();
	} 
		return instance;
}
“懒汉模式”的优缺点:
优点:实现起来简单,当类SingletonTest被加载的时候,静态变量static的instance未被创建并分配内存空间,当getInstance方法第一次被调用时,初始化instance变量,并分配内存,某些特定时间下会节约内存
缺点:在多线程环境中,这种实现方法会有线程安全的问题,会出现多个实例的情况,无法保证在任何时候都是单例的状态。
方式三:线程安全的“懒汉模式”
public class Singleton{
	//构造方法私有化
	private Singleton(){};

	// 将自身实例化对象设置为一个属性,并用static修饰
	private static Singleton instance;
	
	//静态方法返回实例
	public static synchronized  Singleton getInstance(){
		if(instance == null){
			instance = new Singleton();
	} 
		return instance;
}
线程安全的“懒汉模式”的优缺点:
优点:实现起来简单。
缺点:,在jdk1.6之后synchronized关键字进行了优化,但是对性能还是有影响。当使用synchronized  放在静态方法上时,整个类都被锁定了,效率低下。
方式四:DCL双检查锁机制(DCL:double checked locking)
public class Singleton{
	//构造方法私有化
	private Singleton(){};

	// 将自身实例化对象设置为一个属性,并用static修饰
	//CPU执行时候转化成JVM指令执行
  	//1.分配内存给这个对象
  	//2.初始化对象
  	//3.将分配好的对象和内存地址关联,赋值
  	//4.用户访问
  	//可能会出现指令重排
	private volatile static Singleton instance;
	
	//静态方法返回实例
	public static synchronized  Singleton getInstance(){
	//如果第一次检查instance,没有进入if中
	   if(instance == null){
		  synchronized(Singleton.class){
		  	//某个线程取得了类锁,实例化对象前第二次检查instance是否已经被实例化出来,如果没有,才最终实例出对象
		  	if(instance == null){
		  	instance = new Singleton();
		  	}
		  }  
	} 
		return instance;
}
DCL的优缺点:
优点:内存占用率高,效率高,线程安全,多线程操作原子性。
方式五:内部类实现(Inner)
public class Singleton{
 
	
	private Singleton() {
	//判断为null,,抛出异常
	if(SingletonHolder.instance==null){
		 throw new RuntimeException("不允许构建多个实例");
	}
	};
	
	private static class SingletonHolder{
		private static Singleton instance=new Singleton();
	} 
	
	public static Singleton getInstance(){
		return SingletonHolder.instance;
	}
}
Inner的优缺点:
优点:巧妙的利用了内部类的特点(类的静态属性只有在第一次加载类的时候才会被初始化),完美的避免了线程安全的问题,性能优越。
缺点:构造方法虽然私有了,,但是反射依然能获得私有的构造方法。
方式六:枚举法(enum)
public class User{
	//私有化构造函数
	private User(){}

	//定义一个静态枚举类
	static enum SingletonEnum{
		//创建一个枚举对象,该对象天生为单例
		INSTANCE;
		private User user;
		//私有化枚举的构造函数
		private SingletonEnum(){
			user=new User();
		}
		public User getInstance(){
			return user;
		}
	}
	//对外暴露一个获取User对象的静态方法
    public static User getInstance(){
        return SingletonEnum.INSTANCE.getInstnce();
    }
}

总结:

任何一种设计模式都有优点和缺点,,单例模式也不例外:

    优点:   	 1.在内存中只有一个实例,,减少了内存开销。
		     2.可以避免对资源的多重占用。
	     	 3.设置全局访问点,严格控制访问。
	缺点: 如果要扩展单例对象,,只能修改代码。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值