Java教程

设计模式之单例模式

本文主要是介绍设计模式之单例模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

单例模式

定义

在整个程序中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象的方法。

饿汉式(静态常量)

构造器私有化,无法通过new创建对象,在类的内部完成对象的创建,对外提供一个静态方法,返回该对象的实例。

/**
 * 饿汉式静态常量的实现方式
 */
public class HungryStaticConstant {

    //构造器私有化,无法通过new创建对象,
    private HungryStaticConstant(){}

    private final static HungryStaticConstant hungryStaticConstant = new HungryStaticConstant();

    //对外提供一个静态方法,返回该对象的实例
    public static HungryStaticConstant getInstance(){
        return hungryStaticConstant;
    }
}

优点: 写法简单,类装载的时候完成了实例化,避免了线程同步的问题。
缺点: 没有完成懒加载的效果,如果没有用到这个实例会造成资源浪费。

饿汉式(静态代码块)

与静态常量类似

/**
 * 饿汉式(静态代码块实现)
 */
public class HungryStaticCodeBlock {
    //构造器私有化,无法通过new创建对象,
    private HungryStaticCodeBlock(){}

    private static HungryStaticCodeBlock hungryStaticCodeBlock;

    //静态代码块,返回实例对象
    static{
        hungryStaticCodeBlock = new HungryStaticCodeBlock();
    }

    //对外的静态方法,返回对象的实例
    public static HungryStaticCodeBlock getInstance(){
        return hungryStaticCodeBlock;
    }
}

优点缺点同饿汉式(静态常量)

懒汉式(线程不安全)

/**
 * 线程不安全的懒汉式实现
 */
public class LazyNonSafeThread {

    private static LazyNonSafeThread lazyNonSafeThread;

    //构造函数私有化
    private LazyNonSafeThread(){}

    //提供一个静态方法,当使用该方法时才创建实例
    public static LazyNonSafeThread lazyNonSafeThread(){
        if(lazyNonSafeThread == null){
            //没创建时,创建实例
            lazyNonSafeThread = new LazyNonSafeThread();
        }
        return lazyNonSafeThread;
    }
}

优点: 起到了懒加载的效果,但是只能在单线程下使用。
缺点: 如果多线程的情况下,多个线程都进入到了if判断的情况中就会产生多个实例,就不是单例模式了。

懒汉式(线程安全)

/**
 * 懒汉式线程安全的实现方式
 */
public class LazySafeThread {

    private static LazySafeThread lazySafeThread;

    //构造函数私有化
    private LazySafeThread(){}

    //提供一个静态方法,当使用该方法时才创建实例
    public static synchronized LazySafeThread lazySafeThread(){
        if(lazySafeThread == null){
            //没创建时,创建实例
            lazySafeThread = new LazySafeThread();
        }
        return lazySafeThread;
    }
}

问题: 效率太低,获取线程实例的时候每次都要进行同步。

双重检查实现单例模式

/**
 * 单例模式双重检查实现方式
 */
public class DoubleCheck {
    
    //增加volatile关键字
    private static volatile DoubleCheck doubleCheck;

    private DoubleCheck(){}

    public static DoubleCheck doubleCheck(){
        //第一层检查
        if(doubleCheck == null){
            synchronized (DoubleCheck.class){
                //第二层检查
                if(doubleCheck == null){
                    doubleCheck = new DoubleCheck();
                }
            }
        }
        return doubleCheck;
    }
}

解决了线程安全问题,同时也解决了懒加载问题。
实际开发中推荐使用这种单例设计模式。

静态内部类

/**
 * 静态内部类实现单例模式
 */
public class StaticInnerClass {

    private StaticInnerClass(){}

    //类装载的时候静态内部类不会装载
    private static class InnerClass{
        private final static StaticInnerClass staticInnerClass = new StaticInnerClass();
    }

    public static StaticInnerClass getInstance(){
        return InnerClass.staticInnerClass;
    }

}

当调用getInstance时才会装载内部类,装载时是线程安全的,所以此方法也是线程安全的并且兼顾懒加载的特性。

此外还可以同步借助枚举来实现单例模式,不仅能避免多线程的同步问题,而且还能通过反序列化重新创建对象,也是《EFFECTIVE JAVA》的作者Josh Bloch提倡的方式
在Java中Runtime就是经典的单例模式:
在这里插入图片描述
使用场景: 需要频繁创建和销毁对象,重量级对象(创建对象耗时过多或消耗资源过多),经常用到的对象、工具类对象等。

这篇关于设计模式之单例模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!