java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java 设计模式

JAVA设计模式零基础解析之单例模式的八种方式

作者:龍弟-idea

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性

单例模式简介:

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建Session对象。SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory就够,这是就会使用到单例模式。

单例模式优点:

应用场景:

单例模式其核心在于在整个系统中只创建唯一一个实例,其应用场景主要如下:

单例设计模式的八种方式:

1、饿汉式(静态常量)

应用实例:

public class SingletonTest01 {
    public static void main(String[] args) {
        //测试
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1=instance1);    //true
        System.out.println("instance1.hsashCode="+instance1.hashCode());
        System.out.println("instance2.hsashCode="+instance2.hashCode());
    }
}
//饿汉式顾名思义是饥饿的,因此应该开始就创建对象
class Singleton{
    // 1.构造器私有化,外部不能new
    private Singleton(){
    }
    // 2.本类内部创建对象实例
    private final static Singleton instance=new Singleton();
    // 3.提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance(){
        return instance;
    }
}

运行结果:

优缺点说明:

结论:这种单例模式可用,但是可能造成内存浪费

2、饿汉式(静态代码块)

class Singleton01{
    // 1.构造器私有化,外部不能new
    private Singleton01(){
    }
    // 2.本类内部创建对象实例
    private  static Singleton01 instance;
    static {  //在静态代码块中,创建单例对象
        instance=new Singleton01();
    }
    // 3.提供一个公有的静态方法,返回实例对象
    public static Singleton01 getInstance(){
        return instance;
    }
}

优缺点说明:和上面一样这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也就是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。

3、懒汉式(线程不安全)

public class SingletonTest03 {
    public static void main(String[] args) {
        //测试
        System.out.println("懒汉式,线程不安全~");
        Singleton03 instance1 = Singleton03.getInstance();
        Singleton03 instance2 = Singleton03.getInstance();
        System.out.println(instance1==instance2);    //true
        System.out.println("instance1.hsashCode="+instance1.hashCode());
        System.out.println("instance2.hsashCode="+instance2.hashCode());
    }
}
//懒汉式顾名思义就是懒,不会跟饿汉式一样上来就创建对象,而是在需要的时候才会创建,而且是仅创建一次
class Singleton03{
    // 1.构造器私有化,外部不能new
    private Singleton03(){
    }
    // 2.本类内部创建对象实例
    private  static Singleton03 instance;
 
    // 3.提供一个公有的静态方法,当使用到该方法时,才会去创建instance
    //即懒汉式
    public static Singleton03 getInstance(){
        if(instance==null){
            instance=new Singleton03();
        }
        return instance;
    }
}

运行结果:

优缺点说明:

4、懒汉式(线程安全,同步方法)

class Singleton04{
    // 1.构造器私有化,外部不能new
    private Singleton04(){
    }
    // 2.本类内部创建对象实例
    private  static Singleton04 instance;
    // 3.提供一个公有的静态方法,加入同步处理的代码,解决线程安全问题
    //即懒汉式
    public static synchronized  Singleton04 getInstance(){
        if(instance==null){
            instance=new Singleton04();
        }
        return instance;
    }
}

运行结果:

优缺点说明:

5、懒汉式(线程安全,同步代码块)

class Singleton05{
    // 1.构造器私有化,外部不能new
    private Singleton05(){
    }
    // 2.本类内部创建对象实例
    private  static Singleton05 instance;
    // 3.提供一个公有的静态方法,加入同步代码块
    public static Singleton05 getInstance(){
        if(instance==null){
          synchronized (Singleton05.class){
              instance=new Singleton05();
          }
        }
        return instance;
    }
}

优缺点说明:

结论:在实际开发中,不能使用这种方式

6、双重检查(推荐使用)

//双重检查
class Singleton06{
    // 1.构造器私有化,外部不能new
    private Singleton06(){
    }
    // 2.本类内部创建对象实例
    private  static volatile Singleton06 instance;
    // 3.提供一个公有的静态方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题
    public static synchronized Singleton06 getInstance(){
        if(instance==null){
          synchronized (Singleton06.class){
              if(instance==null){
                  instance=new Singleton06();
              }
          }
        }
        return instance;
    }
}

运行结果:

优缺点说明:

为什么一定使用volatile?

在java内存模型中,volatile 关键字作用是:

7、静态内部类(推荐使用)

//静态内部类完成,推荐使用
class Singleton07{
    // 1.构造器私有化
    private Singleton07(){
    }
    // 2.本类内部创建对象实例
    private  static volatile Singleton07 instance;
    //写一个内部静态类,该类中有一个静态的属性
    private static class SingletonInstance{
        private static final Singleton07 INSTANCE=new Singleton07();
    }
    // 3.提供一个公有的静态方法,直接返回SingletonInstance.INSTANCE
    public static synchronized Singleton07 getInstance(){
 
        return SingletonInstance.INSTANCE;
    }
}

运行结果:

优缺点说明:

8、枚举(推荐使用)

public class SingletonTest08 {
    public static void main(String[] args) {
        Singleton08 instance = Singleton08.INSTANCE;
        Singleton08 instance2 = Singleton08.INSTANCE;
        System.out.println(instance==instance2);
 
        System.out.println(instance.hashCode());
        System.out.println(instance2.hashCode());
        instance.sayOk();
    }
}
//使用枚举,可以实现单例,推荐
enum Singleton08{
    INSTANCE;//属性
    public void sayOk(){
        System.out.println("ok~");
    }
}

运行结果:

优缺点:

单例模式在JDK应用的源码分析

在我们JDK中,java.lang.Runtime就是经典的单例模式(饿汉式)
从以下源码可以看出:

单例模式注意事项和细节说明

到此这篇关于JAVA设计模式零基础解析之单例模式的八种方式的文章就介绍到这了,更多相关Java 设计模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文