设计模式:单例模式

最近谷咕咕在学习设计模式,都说不会设计模式的程序员是读不懂框架源码的,而且写出的代码是架构底下的。行吧,那只好卷一下,看看各个设计模式的优点。
这里先是看了狂神的视频,然后对照菜鸟教程浏览了一下,其中不懂的知识点就去百度,当然百度了也不懂的,大可不必太深究。总结:还是要自己敲代码,运行,看结果去理解。光看要是不懂的话不用太烦,反正是挺晦涩的。
首先看最简单的设计模式:

单例模式

提供创建的对象的最佳方式。
注意:
1.单例类只能有一个实例。
2.单例类必须自己创建自己的唯一实例。
3.单例类必须给所以其他对象提供这一实例。

关键:构造器私有,私有保证只能自己创建自己的实例。
实现单例的多种方式
1.懒汉式
通俗来讲,就是比较懒,不用的时候就没有这个实例,用到了才创建对象实例。
懒汉式,下面的3的代码就是在懒汉式上写的。

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

要是想线程安全就锁上类

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

2.饿汉式
饿汉式其实就是在类装载的时候就实例化,容器造成垃圾对象。

package single;

/**
 * @author ymgu
 * @version V1.0
 * @Package single
 * @date 2022/3/21 10:59
 */
public class Hungry {
    private Hungry(){

    }
    private final  static  Hungry HUNGRY=new Hungry();
    public static Hungry getInstance(){
        return HUNGRY;
    }
}

3.双重校验锁
所谓的双重校验锁其实就是使用synchronized 锁住类,然后volatile防止指令重排

package single;

import java.lang.reflect.Constructor;

/**
 * @author ymgu
 * @version V1.0
 * @Package single
 * @date 2022/3/21 9:58
 */
public class LazyMan {
    //单例模式一定要构造器私有
    private  LazyMan(){
        synchronized (LazyMan.class){
            if(lazyMan!=null){
                throw  new RuntimeException("不要通过反射破坏单例");
            }
        }
    }
    //防止指令重排volatile
    private volatile static  LazyMan lazyMan;

    public  static  LazyMan getInstance(){
        if (lazyMan==null){
            //锁住该类,防止出现多线程创建多个对象
            synchronized (LazyMan.class){
                if (lazyMan==null){
                    lazyMan=new LazyMan();
                }
            }
        }
        return lazyMan;
    }

    public static void main(String[] args) throws Exception {
        LazyMan lazyMan=LazyMan.getInstance();
        Constructor<LazyMan> declaredConstructor=LazyMan.class.getDeclaredConstructor(null);
        //破坏其的私有权限
        declaredConstructor.setAccessible(true);
        LazyMan lazyMan2=declaredConstructor.newInstance();
        System.out.println(lazyMan);
        System.out.println(lazyMan2);

    }

}

4.静态内部类
今天内部类的实现方式和双重校验锁效果一样,但是可以延迟初始化,这一块吧,我就没有深究。

package single;

import com.sun.org.apache.bcel.internal.classfile.InnerClass;

/**
 * @author ymgu
 * @version V1.0
 * @Package single
 * @date 2022/3/21 10:08
 */
public class Holder {
    private  Holder(){
    }
    public static  Holder getInstance(){
        return InnerClass.HOLDER;
    }
    public  static  class  InnerClass{
        private  static final Holder HOLDER=new Holder();
    }

}

5.枚举
如果通过反射来破坏,就会报异常,enum是实现了方式反射的
在这里插入图片描述

package single;

import java.lang.reflect.Constructor;

/**
 * @author ymgu
 * @version V1.0
 * @Package single
 * @date 2022/3/21 10:34
 */
//反射不能破坏枚举的单例
public enum EnumSingle {
    INSTANCE;
    public EnumSingle getInstance(){
        return  INSTANCE;
    }
}
class Test{
    public static void main(String[] args) throws Exception {
        EnumSingle enumSingle1=EnumSingle.INSTANCE;
        EnumSingle enumSingle2=EnumSingle.INSTANCE;
        System.out.println(enumSingle1);
        System.out.println(enumSingle2);
        Constructor<EnumSingle> declaredConstructor=EnumSingle.class.getDeclaredConstructor(String.class,int.class);
        declaredConstructor.setAccessible(true);
        EnumSingle enumSingle3=declaredConstructor.newInstance();
        System.out.println(enumSingle3);

    }
}

最后引用菜鸟的话
经验之谈:一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

谷咕咕

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

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

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

打赏作者

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

抵扣说明:

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

余额充值