Java设计模式—单例模式

Java设计模式—单例模式



前言

大家好!我是oy,今天给大家讲讲我对单例模式的见解,欢迎提出您的想法。


一、开始

首先讲讲单例模式这四个字。“模式”也可以理解为模板、公式。“单例”可以理解为单个实例。实例应该都知道是什么意思吧。就是类的实例化。类的对象。所以组合一起就是,单例模式即为设计某个类只有一个实例的一种模板。那么它有什么用呢?比如需要用到类的对象时,不需要每次都new对象使用,只需要在类中就定义好这个类的实例,减少了系统开销。

二、进入

1.单例模式的例子

根据单例模式的特征,现在来写一下代码。
1.只有一个实例。那么就是得把实例作为该类的属性同时需要用static表示其唯一,用private来体现一下封装性吧更美观。
2.创建类的对象需要有构造器吧,因为只能有一个实例,也就是说外部不能创建这个类的对象,所以构造器必须私有化。
3.这个对象是私有的就必须提供权限为public的方法获取。

示例一:饿汉式
public class Order {
    private static Order instance = new Order();
    private Order() {}
    public static Order getInstance() {
        return instance;
    }
}

现在其实就完成了单例模式的代码了。Order类只有一个实例就是instance。但其实单例模式有两种写法。上面这种叫做饿汉式。还有一种叫懒汉式。下面写一下懒汉式。

示例二:懒汉式
public class Order {
    private static Order instance = null;
    private Order() {}
    public static Order getInstance() {
        if (instance == null) {
            instance = new Order();
        }
        return instance;
    }
}

上下两种有什么区别?饿汉式instance直接赋值了,而懒汉式instance为null。这其实就是两种方式的区别。至于getInstance方法是为了返回instance给调用者。肯定不能返回null。就需要先进行判空,为空则创建类的实例后再返回。到这里其实已经讲完了Java设计模式的单例模式了。学习单例模式可以就到这里为止,掌握了Java多线程,请再仔细研究当前的懒汉式的单例模式有什么问题!!

三、深入

1.懒汉式的问题

接着就涉及Java多线程中的同步问题了。可以仔细看看第二种懒汉式的单例模式。instance的初始值为null。调用getInstance每次会进行判空再返回值。如果多个线程一起调用getInstance的时候。就可能出现多次初始化instance了。那么instance也就不唯一了,完全不符合单例模式的核心。

你好
比如进程1调用getInstance,进入判断instance为空,线程1要进行创建instance,假设在其创建[ new Order() ]之前,进程2也调用getInstance(多线程情况下是可能发生的),进入判断instance,此时instance为空,线程2也进行创建instance,会导致,进程1和进程2获取的instance不是同一个。这就是懒汉式导致的多线程问题。

2.解决

为解决这个问题,就需要为getInstance方法加锁。阻止线程1调用getInstace方法时,其他线程也调用getInstance。简单说一下加锁,就是限制对共享数据的操作,使用synchronized把对共享数据的操作包起来。使得线程1执行完操作共享数据后,线程2才可以执行(学完多线程更能明白)

加锁方式有五种
// 法一 直接枷锁
public static synchronized Order getInstance() { // 这种其实也是Order类对象加锁
    if (instance == null) {
        instance = new Order();
    }
    return instance;
}
// 法二
public static Order getInstance() {
    synchronized(Order.class) { // 用Order类对象加锁
        if (instance == null) {
            instance = new Order();
        }
        return instance;
    }
}
// 法三 只是效率比前两者更高
public static Order getInstance() {
    if (instance == null) {  // 也是Order类对象加锁
        synchronized(Order.class) {
            if (instance == null) {
                instance = new Order();
            }
        }
    }
    return instance;
}
// 法四 静态内部加载
public class Order {
    private static class Order() {
        private static Order instance = new Order();
    }
    private Order(){}
    public static Order getInsatnce() {
        return Order.instance;
    }
}
// 法五 枚举方法
public enum Order {
    INSTANCE; // INSTANCE就是Order的单例
    public void doSomething() {
        // 要做的事情
    }
}


总结

以上就是今天要讲的内容,本文仅仅介绍了Java设计模式中的单例模式,而具体使用需要在项目中灵活改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

勤奋的oyoung

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

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

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

打赏作者

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

抵扣说明:

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

余额充值