[关闭]
@linux1s1s 2015-08-26T15:28:35.000000Z 字数 1671 阅读 3373

Java设计模式 -- Singleton模式

Java设计模式


我们先来看看网上比较流行的几种单例模式:

非线程安全

  1. public class Singleton {
  2. private Singleton() {}
  3. private static Singleton single=null;
  4. public static Singleton getInstance() {
  5. if (single == null) {
  6. single = new Singleton();
  7. }
  8. return single;
  9. }
  10. }

单边加锁

  1. public static synchronized Singleton getInstance() {
  2. if (single == null) {
  3. single = new Singleton();
  4. }
  5. return single;
  6. }

双边加锁

  1. public static Singleton getInstance() {
  2. if (singleton == null) {
  3. synchronized (Singleton.class) {
  4. if (singleton == null) {
  5. singleton = new Singleton();
  6. }
  7. }
  8. }
  9. return singleton;
  10. }

嵌套类实现

  1. public class Singleton {
  2. private static class LazyHolder {
  3. private static final Singleton INSTANCE = new Singleton();
  4. }
  5. private Singleton (){
  6. }
  7. public static final Singleton getInstance() {
  8. return LazyHolder.INSTANCE;
  9. }
  10. }

有没有发现这些流行的代码都没有涉及带有参数的单例模式,如果单例需要传入参数,该如何实现,如果实现不能再套用上面的代码,那么问题来了,该如何处理?
我们先假设,直接把参数按照原先的代码样式传过来,如下所示

带有参数的单例实现

  1. public static Singleton getInstance(final Object object) {
  2. if (singleton == null) {
  3. synchronized (Singleton.class) {
  4. if (singleton == null) {
  5. singleton = new Singleton(object);
  6. }
  7. }
  8. }
  9. return singleton;
  10. }

这里给出了双边加锁传入参数的例子,单边加锁和嵌套类实现道理相同。虽然代码轻易实现了,但是先别高兴,如果仔细看看代码,你会发现,如果传入不同的参数是不是可能导致单例不再是同一个实例了呢?即使能保证单例,但是语义上已经完全不符合单例的要求,所以该换个更符合实际项目的单例模式,这里仅仅给出双边加锁的线程安全单例代码如下

推荐单例实现

  1. public class DeviceInfoManager {
  2. private static DeviceInfoManager DEVICE_INFO_MANAGER = null;
  3. private DeviceInfoManager(final Context context) {
  4. //TODO
  5. }
  6. public static void createInstance(final Context context) {
  7. if (DEVICE_INFO_MANAGER == null) {
  8. synchronized (DeviceInfoManager.class) {
  9. if (DEVICE_INFO_MANAGER == null) {
  10. DEVICE_INFO_MANAGER = new DeviceInfoManager(context);
  11. }
  12. }
  13. }
  14. }
  15. public static DeviceInfoManager getInstance() {
  16. if (DEVICE_INFO_MANAGER == null) {
  17. throw new NullPointerException("getInstance() is Null, please call DeviceInfoManager.createInstance(context) first!");
  18. }
  19. return DEVICE_INFO_MANAGER;
  20. }
  21. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注