5种单例模式--初学者版

来源:互联网 发布:mac大写字母自动切换 编辑:程序博客网 时间:2024/06/15 10:47
       java中单例模式是一种常见的设计模式,单例模式有:懒汉式单例、饿汉式单例等。
  单例模式有以下特点:
  1、单例类只能有一个实例。
  2、单例类必须自己创建自己的唯一实例。

  3、单例类必须给所有其他对象提供这一实例。

   其他具体定义可参考百度百科,这里就不介绍了。这里主要列出5种比较常见的单例模式的写法:

    

一:饿汉式:就像饿了的汉子,迫不及待的就创建一个对象

     /**饿汉式单例(类加载时则创建对象) */
class Single01{ //加载类就是将类读到内存(代码区)
    private Single01() {}
    /**类加载时构建对象*/
    private static Single01 instance=new Single01();
    /**提供一个public的方法访问instance*/
    public static Single01 getInstance(){
        return instance;
    }
}


二:懒汉式:好像一个懒汉,不用时就不创建对象,什么时候使用就什么时候创建 instance对象

class Single02{
    private Single02() {}
    private static Single02 instance;
    public  static Single02 getInstance() {
        if(instance==null){
          synchronized (Single02.class) {
            if(instance==null){
                instance=new Single02();
            }
          }
        }
        return instance;
    }
}

     由于懒汉式本身线程非安全,所以在这加了一个同步代码块,用同步代码锁使线程安全。初学者可暂时不考虑安全问题,getInstance()方法中可省略至如下:

 public  static Single02 getInstance() {
                instance=new Single02();

                return instance;       

}


三:构建一个静态内部类,在内部类中构建instance对象,有点类似于饿汉式,创建变量时就创建对象。但相比于饿汉式,此方法的优点在于静态内部类在外部类加载时并不加载,只有在调用内部类时才加载到内存中。在一定情况下可以节省内存,提高效率。缺点是多构建了一个内部类。

class Single03{
    private Single03(){}
    static class Inner{
        public static  Single03 instance= new Single03();
    }
    public static Single03 getInstance(){
        return Inner.instance;
    }
}

四:利用枚举类构建单例

enum Single04{
    INSTANCE;
}

五:线程内部单例(初学者,未接触多线程可略过)借助ThreadLocal实现,一个线程创建一份某个类的实例,实现线程内的单例。


class Single05{
    private Single05() {}
    private static ThreadLocal<Single05> td=new ThreadLocal<>();
    public static Single05 getInstance(){
        //1.从当前线程获得实例
        Single05 instance=td.get();
        //2.当前线程没有则创建实例
        if(instance==null){
        instance=new Single05();
        //3.创建实例以后要绑定到当前线程
        td.set(instance);
        }
        return instance;
    }
}

main方法中就举一个例子吧,基本构建方式类似

public class DanLi {
    public static void main(String[] args) {
        Singleton03 s1=Singleton03.getIns();
        Singleton03 s2=Singleton03.getIns();
        Singleton03 s3=Singleton03.getIns();
        System.out.println("s1="+s1);
        System.out.println("s2="+s2);
        System.out.println("s3="+s3);

   }

}

运行完可以验证地址值都是一样的。


     以上就是个人总结的几种单例模式,从这几种单例模式中可以看出,要创建单例:首先要私有化构造函数;其次私有化属性;最后公有化一个方法(使外部可以通过该方法构建对象)。


0 0