设计模式之一单例设计模式

一、使用场景

单例设计模式是应用最广的设计模式,例如:当创建一个对象需要消耗过多的资源,如要访问IO或数据库等资源,这时就要考虑用单例模式;在一个应用中,应该只有一个ImageLoader实例,这个ImageLoader中又有线程池、缓存系统、网络请求等,很消耗资源,一般用单例模式。

二、如何实现

1、构造函数私有化。

2、通过静态方法或者枚举返回单例对象。

3、确保单例对象有且只有一个,尤其是在多线程环境下。

4、确保单例对象在反序列化下不会重新构建对象。

三、代码实现

1、饿汉单例模式

public class Singleton {

    private static final Singleton instance=new Singleton();

    private Singleton() {

   }

    public static Singleton getInstance() {

                  return instance;

     }

}

2、懒汉式

懒汉单例模式的优点是单例只有在使用时才会初始化,在一定程度上节约了资源。缺点是第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都进行同步,造成不必要的同步开销,不建议使用。

public class Singleton {

      private static Singleton instance;

      private Singleton(){

    }

      public static Synchronized Singleton getInstance(){

           if(instance==null){

                   instance=new Singleton();

          }

         return instance;

     }

}

3、Double Check Load(DCL)

优点是既能在需要时才初始化单例,又能保证线程安全,且单例模式初始化时调用getInstance不进行同步锁。缺点是在第一次加载时反应稍慢,由于java 内存模型的原因偶尔会加载失败,在高并发环境下也存在一定缺陷,但是概率较小。除非代码并发场景较复杂,或者在JDK 6版本以下,否则该种模式一般满足条件。该种模式也是使用较多的模式。

public class Singleton {

      private static Singleton instance=null;

      private Singleton(){

   }

     public static Singleton getInstance(){

         if(instance==null){

              synchronized(Singleton.class){

                    if(instance==null){

                           instance=new Singleton();

                   }

            }

        }

          return instance;

    }

}

4、静态内部类单例模式

此种方法解决DCL模式不能在线程并发复杂情况下使用问题,此为推荐使用模式。

public class Singleton {

     private Singleton() {

    }

     public static Singleton getInstance() {

             return SingletonHolder.singleton;

   }

/**

*静态内部类

*/

      private static class SingletonHolder {

           private static fina lSingleton singleton=new Singleton();

    }

}

5、枚举单例

此种方法写法简单,线程安全,并且防止反序列化重新生成对象。

publc enum SingletonEnum{

INSTANCE;

}

以上构建单例模式方法中,为了避免反序列化重新生成对象,加入以下方法

private Object readResolve() throws ObjectSteamException{

return instance;

}

6、使用容器实现单例

这种方式使得我们可以管理多种类型的单例,并且使用时可以用统一的接口进行获取操作,降低用户使用成本,也对用户隐藏了具体实现,降低了耦合度。

public class SingletonManager {

     private static Map objMap = new HashMap();

     private SingletonManager(){}

     public static void registerService(String key,Object instance){

              if(!objMap.containsKey(key)){

                       objMap.put(key,instance);

         }

}

     public static ObjectgetService(String key){

                  return objMap.get(key);

   }

}

不管以哪种方式实现单例模式,其核心都是构造器私有化,并且通过静态方法获取唯一实例,在获取过程中必须保证线程安全、防止反序列化重新生成实例等问题。当然,选择那种方式,取决于项目本身。

你可能感兴趣的:(设计模式之一单例设计模式)