设计模式学习(二)单例模式

 

目录

1.饿汉式单例

2.懒汉式单例

3.单例模式完美解决方案


  单例模式(Singleton Pattern)是指确保一个类在一个容器下只有一个实例存在,并提供一个全局访问点。

    (单例模式最大的特点就是构造方法私有化)

1.饿汉式单例

UML类结构图:

定义:

    饿汉式单例是在类加载的时候就立即初始化,并且创建单例对象。绝对线程安全,在线程还没出现以前就实例化了,不可能存在访问安全问题。
    (Spring IOC容器中ApplicationContext本身就是典型的饿汉式单例。)

优点:

    没有加任何的锁,执行效率比较高,在用户体验上来说,比懒汉式更好。

缺点:

    类加载的时候就初始化,不管用与不用都占用着空间,浪费内存。

代码实现:

HungrySingletonTest类

写法一:

public class HungrySingletonTest {
    //写法一
    private static final HungrySingletonTest hungrySingletonTest = new HungrySingletonTest();
    private HungrySingletonTest() {}
    public static HungrySingletonTest getInstance() {
        return hungrySingletonTest;
    }
}

写法二:

public class HungrySingletonTest {
    // 写法二
    private static HungrySingletonTest hungrySingletonTest;
    static {
        hungrySingletonTest = new HungrySingletonTest();
    }
    private HungrySingletonTest() {}
    public static HungrySingletonTest getInstance() {
        return hungrySingletonTest;
    }
}

注意:

    饿汉式虽然是线程安全的,但是如果我们使用FileInputStream / FileOutputStream配合ObjectInputStream / ObjectOutputStream来把实例序列化之后,再反序列化回来,还是会变成两个对象。

解决方法:

    需要在单例类中实现Serializable序列化接口,并且实现readResolve()方法,这是序列化和反序列化的一个协议,为了序列化后的对象能够重复利用,可以实现readResolve()方法,而这个方法是由JVM自动调用的。

private Object readResolve() {
    return INSTANCE; // 返回饿汉式中的静态实例
}

2.懒汉式单例

类结构图:

定义:

    懒汉式单例的特点是:被外部类调用的时候单例类才会实例化。

优点:

    当单例类被外部类调用的时候单例类才会实例化,相比饿汉式不会浪费内存。

缺点:

    容易出现线程安全,如果用双重锁保证线程安全,也会因此降低性能。

代码实现:

LazySingletonTest类

public class LazySingletonTest {
    private static LazySingletonTest lazySingletonTest;
    private LazySingletonTest() {}
    public static LazySingletonTest getInstance() {
        // 双重锁增加线程安全
        // 第一个if()减少synchronized使用频率,提高性能
        if (lazySingletonTest == null) {
            synchronized (LazySingletonTest.class) {
                // 第二个if()去除已经在并发线程中实例化的变量
                if (lazySingletonTest == null) {
                    lazySingletonTest = new LazySingletonTest();
                }
            }
        }
        return lazySingletonTest;
    }
}

3.单例模式完美解决方案

// 这种形式兼顾饿汉式的内存浪费,也兼顾synchronized性能问题
// 完美地屏蔽了这两个缺点
public class LazySingletonTest {
    // 默认使用LazySingleTest的时候,会先初始化内部类
    // 如果没使用的话,内部类是不加载的
    private LazySingletonTest() {}
    // 每一个关键字都不是多余的
    // static是为了使单例的空间共享
    // 保证这个方法不会被重写,重载
    public static final LazySingletonTest getInstance() {
        // 在返回结果以前,一定会先加载内部类
        return LazyHolder.LAZY;
    }
    // 默认不加载
    private static class LazyHolder {
        private static final LazySingletonTest LAZY = new LazySingletonTest();
    }
}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿放下技术的小赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值