单例模式(Singleton)学习总结
  anLrwkgbyYZS 2023年12月30日 15 0


1. 单例模式(Singleton)简介

单例模式:一个类只能生成一个实例,这个实例由该类自己生成。

主要特点构造函数是 private的,为了禁止外部调用单例类的构造函数,如果在单例类的外部使用去创建( new )单例类的实例会出现编译错误。通常通过单例类的 getInstance() 方法获得单例类的唯一实例,getInstance() 这个方法名不强制、不过通常情况下都是这样命名。

主要解决:解决一个全局使用的类频繁地创建与销毁的问题。例如:MyBatis 中的 SqlSessionFactory 。

2. 单例模式实现

单例模式的实现,有饿汉式、懒汉式。

饿汉式:在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。

懒汉式:在类加载时不初始化,在获取对象时初始化类,类加载比较快,但获取对象的速度快慢。

2.1 饿汉式代码实现

饿汉式代码实现代码如下,加有详细注释。

package Singleton;

/**
 * 饿汉式单例模式实现
 */

public class CommonSingleton {
    // 私有、静态的 CommonSingleton 对象、 初始化
    private static CommonSingleton commonSingleton = new CommonSingleton();

    /**
     * 私有化构造函数,这样该类不能在外部实例化
     * 只能通过 getInstance()  获取 CommonSingleton类 唯一可用的对象
     */
    private CommonSingleton() {
        System.out.println("生成了一个实例");
    }

    /**
     * 获取 CommonSingleton类 唯一可用的对象
     * @return CommonSingleton类 唯一可用的对象
     */
    public static CommonSingleton getInstance() {
        return commonSingleton;
    }
}

测试代码:

package Singleton;

public class Test {
    public static void main(String args[]) {
        CommonSingleton commonSingleton1 = CommonSingleton.getInstance();
        CommonSingleton commonSingleton2 = CommonSingleton.getInstance();
        if(commonSingleton1 == commonSingleton2) {
            System.out.println("commonSingleton1和commonSingleton2 是同一实例对象");
        } else {
            System.out.println("commonSingleton1和commonSingleton2 不是同一实例对象");
        }
    }
}

程序运行截图如下:

单例模式(Singleton)学习总结_System

2.2 懒汉式(线程不安全 )代码实现

懒汉式(线程不安全 )代码实现如下,加有详细注释。

package Singleton;

/**
 * 懒汉单例模式实现
 * 懒汉单例模式:在类加载的时候,不创建实例
 * 优点:类的加载速度快
 * 缺点:获取唯一可用的对象较慢
 */

public class Lazy01Singleton {
    // 私有、静态的 CommonSingleton 对象、 未初始化
    private static Lazy01Singleton lazy01Singleton;

    /**
     * 私有化构造函数,这样该类不能在外部实例化
     * 只能通过 getInstance()  获取 Lazy01Singleton类 唯一可用的对象
     */
    private Lazy01Singleton() {
        System.out.println("生成了一个实例");
    }

    public static Lazy01Singleton getInstance() {
        if (lazy01Singleton == null) {
            lazy01Singleton = new Lazy01Singleton();
        }
        return lazy01Singleton;
    }
}

测试代码:

package Singleton;

public class Test {
    public static void main(String args[]) {
        Lazy01Singleton lazy01Singleton01 = Lazy01Singleton.getInstance();
        Lazy01Singleton lazy01Singleton02 = Lazy01Singleton.getInstance();
        if (lazy01Singleton01 == lazy01Singleton02) {
            System.out.println("lazy01Singleton01和lazy01Singleton02 是同一实例对象");
        } else {
            System.out.println("lazy01Singleton01和lazy01Singleton02 不是同一实例对象");
        }
    }
}

程序运行结果如下:

单例模式(Singleton)学习总结_类加载_02

2.3 懒汉式(线程安全 )代码实现

懒汉式(线程安全 )代码实现如下,加有详细注释。

package Singleton;

/**
 * 线程安全的懒汉单例模式实现
 * 懒汉单例模式:在类加载的时候,不创建实例
 * 优点:类的加载速度快
 * 缺点:获取唯一可用的对象较慢
 */

public class Lazy02Singleton {
    // 私有、静态的 CommonSingleton 对象、 未初始化
    private static volatile Lazy02Singleton lazy02Singleton;

    /**
     * 私有化构造函数,这样该类不能在外部实例化
     * 只能通过 getInstance()  获取 Lazy01Singleton类 唯一可用的对象
     */
    private Lazy02Singleton() {
        System.out.println("生成了一个实例");
    }

    public static Lazy02Singleton getInstance() {
        if (lazy02Singleton == null) {
            // 对这个类加锁
            synchronized (Lazy02Singleton.class) {
                if (lazy02Singleton == null) {
                    lazy02Singleton = new Lazy02Singleton();
                }
            }
        }
        return lazy02Singleton;
    }
}

测试代码如下:

package Singleton;

public class Test {
    public static void main(String args[]) {
        Lazy02Singleton lazy02Singleton01 = Lazy02Singleton.getInstance();
        Lazy02Singleton lazy02Singleton02 = Lazy02Singleton.getInstance();
        if (lazy02Singleton01 == lazy02Singleton02) {
            System.out.println("lazy02Singleton01和lazy02Singleton02 是同一实例对象");
        } else {
            System.out.println("lazy02Singleton01和lazy02Singleton02 不是同一实例对象");
        }
    }
}

程序运行截图如下:

单例模式(Singleton)学习总结_System_03

参考文献:

  • 图解设计模式 - 结成浩著、杨文轩译 - 人民邮电出版社
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月30日 0

暂无评论

anLrwkgbyYZS