单例模式(Singleton pattern)的三种写法(含枚举实现方式)

本文探讨了单例模式的三种常见实现方式,包括懒汉式、饿汉式以及使用枚举的方式。重点讲解了每种方法的原理和特点,特别是在并发环境下的表现。最后,提出了思考问题——如何实现双例模式,以检验读者对单例模式的理解。
摘要由CSDN通过智能技术生成

最近项目组开始找人,试卷上豁然是个经典的问题(话说我毕业那会儿都已经是老题目,如今还在用)那就是,

哥们儿,写个单例模式吧!

恰巧今天早上看《effective java》看到单例模式的一种新写法。就再次分享给大家。希望对大家有用。

单例模式,是最简单的设计模式(之一?),单例对象的类必须保证只有一个实例存在。

方法1.

public class SingletonClass {
	
	/**
	 * (1)私有而且是static的实例,在加载类的时候直接初始化该实例
	 */
	private static final SingletonClass singletonInstance = new SingletonClass();
	
	/**
	 * (2)私有构造器,防止有人new该对象
	 */
	private SingletonClass() {
	}
	
	/**
	 * (3)外部获取实例的唯一接口方式
	 * @return
	 */
	public static SingletonClass newSingletonInstance() {
		return singletonInstance;
	}
	
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			System.out.println(">>" + i + "=" + SingletonClass.newSingletonInstance());
		}
	}
}

特别需要注意注释部分,基本是环环相扣的。

(1)私有的,所以外部无法直接引用,又是static的,所以在没有初始化时是可以调用的,这为下面一步做了铺垫

(2)私有构造器,所以外部无法直接通过new的方式来创建对象

(3)通过静态方法来给出单例对象,这种方法封装了具体初始化对象的方法,就可以“动点手脚”,这里是将类持有的单例对象暴露出去。


方法2.

public class SingletonClass {
	/**
	 * 私有而且是static的实例
	 */
	private static final SingletonClass singletonInstance = null;
	
	/**
	 * 私有构造器,防止有人new该对象
	 */
	private SingletonClass() {
	}
	
	/**
	 * 外部获取实例的唯一接口方式
	 * @return
	 */
	public static SingletonClass newSingletonInstance() {
		//第一次调用时初始化
		if (singletonInstance == null) {
			singletonInstance = new SingletonClass();
		}
		
		return singletonInstance;
	}
	
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			System.out.println(">>" + i + "=" + SingletonClass.newSingletonInstance());
		}
	}
}

看起来,方法1和方法2的方式区别不大,实际上, 如果是初始化需要耗费的资源较多或者该类很少被使用,那么在加载类时是不合适的,选择方法2会比较好。

另外,同事今天提到,如果在并发时,这段代码是有问题的

<span style="white-space:pre">		</span>//第一次调用时初始化
		if (singletonInstance == null) {
			singletonInstance = new SingletonClass();
		}

如果遇到并发,会实例化不止一个实例,解决方案就是解决并发的方案,最简单就是在newSingletonInstance() 上加synchronized。


方法3.

public enum SingletonClass {
	singletonInstance;
	
	private String name = "sig";
	
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			System.out.println(">>" + i + "=" + SingletonClass.singletonInstance.name);
		}
	}
}

这种方法是利用枚举的特性来实现的。实际上,枚举最终还是会被翻译成final static的。

可以参考这篇文章单例模式中为什么用枚举更好,说的比较详细。


综上所述,单例模式作为一种设计模式,可以有多种实现方式,各种方式都是利用语言的某些特性来具体实现。如此,下次学习一个新的语言的时候可以考虑尝试写一个单例。

还稍微想了下,如果需要的是双例呢?可以试试看,看你理解了没?






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值