设计模式(二)单例模式

本文详细介绍了单例模式的概念,包括饿汉式(静态常量和静态代码块)、懒汉式(线程不安全和线程安全)、双重检查锁、静态内部类和枚举类的实现方式。重点探讨了如何在保证线程安全的同时避免资源浪费,适合理解和实践单例模式在软件设计中的应用。
摘要由CSDN通过智能技术生成

一、概念

单例模式(Singleton),也叫单子模式,是一种常用的设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候,整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,显然,这种方式简化了在复杂环境下的配置管理。

特别地,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。事实上,这些应用都或多或少具有资源管理器的功能。例如,每台计算机可以有若干个打印机,但只能有一个 Printer Spooler(单例) ,以避免两个打印作业同时输出到打印机中。再比如,每台计算机可以有若干通信端口,系统应当集中 (单例)管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

综上所述,单例模式就是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种方法。

二、实现

2.1 饿汉式(静态常量)

package example01;

/**
 * 第一种方式:
 * 静态常量饿汉式
 * 缺点:不管用不用到都实例化,造成资源浪费
 */
public class SingletonTest01 {
    public static void main(String[] args) {
        // 测试
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1 == instance2);
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
    }
}

class Singleton{
    // 构造器私有化,外部不能new
    private Singleton (){
    }

    // 创建实例对象
    private final static Singleton instance = new Singleton();

    public static Singleton getInstance(){
        return instance;
    }

}

2.2 饿汉式(静态代码块)

package example02;

/**
 * 第二种方式:
 * 静态代码块饿汉式
 * 缺点:不管用不用到都实例化,造成资源浪费
 */
public class SingletonTest02 {
    public static void main(String[] args) {
        // 测试
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1 == instance2);
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
    }
}

class Singleton{
    // 构造器私有化,外部不能new
    private Singleton (){
    }

    private static Singleton instance;

    static {
        // 在静态代码块里创建单例对象
        instance  = new Singleton();
    }

    public static Singleton getInstance(){
        return instance;
    }

}

2.3 懒汉式(线程不安全)

package example03;

/**
 * 第三种方式:
 * 饿汉式:用到时才实例化
 * 线程不安全
 */
public class SingletonTest03 {
    public static void main(String[] args) {
        // 测试
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1 == instance2);
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
    }
}

class Singleton{
    private static Singleton instance;

    private Singleton(){}

    // 提供一个静态公有方法,使用时才加载
    public static Singleton getInstance(){
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }

}

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

package example04;

/**
 * 第四种方式:
 * 懒汉式
 * 线程安全
 * 缺点:效率太低
 */
public class SingletonTest04 {
    public static void main(String[] args) {
        // 测试
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1 == instance2);
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
    }
}

class Singleton{
    private static Singleton instance;

    private Singleton(){}

    // 提供一个静态公有方法,家兔同步处理的代码,解决线程不安全问题
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }

}

2.5 双重检查

package example05;

/**
 * 第五种方式(推荐):
 * 双重检查
 */
public class SingletonTest05 {
    public static void main(String[] args) {
        // 测试
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1 == instance2);
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
    }
}

class Singleton{
    /// volatile方式指令重排
    private static volatile Singleton instance;

    private Singleton(){}

    // 提供一个静态公有方法,加入双重检查代码。解决线程不安全问题和懒加载问题
    public static synchronized Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                if(instance==null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

}

2.6 静态内部类

package example06;

/**
 * 第六种方式(推荐):
 * 静态内部类
 */
public class SingletonTest06 {
    public static void main(String[] args) {
        // 测试
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1 == instance2);
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
    }
}

class Singleton{
    /// volatile方式指令重排
    private static volatile Singleton instance;

    private Singleton(){}

    // 写一个静态内部类
    private static class SingleInstance{
        private static final Singleton INSTANCE = new Singleton();
    }

    // 提供一个静态公有方法,返回SingleInstance.INSTANCE
    public static Singleton getInstance(){
        return SingleInstance.INSTANCE;
    }
}

2.7 枚举类

package example07;

/**
 * 枚举类
 * 推荐使用
 */
public class SingletonTest07 {

    public static void main(String[] args) {
        // 测试
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1 == instance2);
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
    }
   
}

enum Singleton {
    INSTANCE;

    public static Singleton getInstance(){
        return Singleton.INSTANCE;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值