重温设计模式之单例

1. 概念

单例模式是什么?
1)为了确保系统全过程中只产生一个实例。
2)当我们再应用中遇到功能性冲突是,需要使用单例模式

为啥要使用单例模式
生活中单例的例子
配置文件:如果不是单例的,两个配置文件内容是一样的,那么有一个是浪费的,如果不一样,那么该以谁为准呢。

2. 实例

可以顺带回顾下类装载到JVM的顺序
自上而下 【声明在前,使用在后】
先属性后方法
先静态后动态

不管class是否实例化,static静态块总会在classloader执行完毕之后,就加载完毕
静态块中只能访问静态属性和静态方法
只要是静态修饰的方法和属性都可以用class .的方式调用
JVM 内存中的静态区,这块内容是公共的。

单例模式的类别
1)懒汉式 【需要用实例的时候才会初始化】
2)饿汉式 【不管是否使用,先实例化】
3)登记式【相当于有容器来状态所有的实例,在实例产生之前,先检查容器有没有,如果有,直接取出来,没有的话就new一个放进容器再给后面的任用,spring IOC就是典型的注册登记式单例】

懒汉式
1)第一种写法

/**
 * @ClassName SingletonDemo2
 * @Description 懒汉式单例,第一次调用时实例化
 * @Autuor lulinfeng
 * @Date 2020/9/17
 * @Version 1.0
 */
public class SingletonDemo2 {

    //第一步,构造函数私有化,在反射面前无用
    private SingletonDemo2() {
    }

    //第二步,声明一个静态变量来保存单例的引用
    private static SingletonDemo2 singletonDemo2 = null;

    //第三步,通过提供静态方法来获取单例的引用
    public static SingletonDemo2 getInstance() {
        if (singletonDemo2 == null) {
            singletonDemo2 = new SingletonDemo2();
        }
        return singletonDemo2;
    }
}

2)第二种写法 getInstancece方法增加synchronize

/**
 * @ClassName SingletonDemo2
 * @Description 懒汉式单例,第一次调用时实例化
 * @Autuor lulinfeng
 * @Date 2020/9/17
 * @Version 1.0
 */
public class SingletonDemo2 {

    //第一步,构造函数私有化,在反射面前无用
    private SingletonDemo2() {
    }

    //第二步,声明一个静态变量来保存单例的引用
    private static SingletonDemo2 singletonDemo2 = null;

    //第三步,通过提供静态方法来获取单例的引用
    public static synchronized SingletonDemo2 getInstance() {
        if (singletonDemo2 == null) {
            singletonDemo2 = new SingletonDemo2();
        }
        return singletonDemo2;
    }
}

3)双重检查锁定

/**
 * @ClassName SingletonDemo2
 * @Description 懒汉式单例,第一次调用时实例化
 * @Autuor lulinfeng
 * @Date 2020/9/17
 * @Version 1.0
 */
public class SingletonDemo2 {

    //第一步,构造函数私有化,在反射面前无用
    private SingletonDemo2() {
    }

    //第二步,声明一个静态变量来保存单例的引用
    private static SingletonDemo2 singletonDemo2 = null;

    //第三步,通过提供静态方法来获取单例的引用
    public static SingletonDemo2 getInstance() {
        if (singletonDemo2 == null) {
            synchronized (SingletonDemo2.class){
                if (singletonDemo2 == null) {
                    singletonDemo2 = new SingletonDemo2();
                }
            }
        }
        return singletonDemo2;
    }
}

4)静态内部类【强烈推荐】

//懒汉式写法(静态内部类)
//既解决了性能问题,也解决了安全性问题
public class SingletonDemo1 {
   
   //1) 首先声明了一个静态内部类
   // private 私有属性保证别人无法修改
   // static 确保全局唯一
   private static class LazyHolder {
       //final 为了防止内部误操作
       private static final SingletonDemo1 INSTANCE = new SingletonDemo1();
   }
   
   //2)默认构造私有化
   private SingletonDemo1(){}

   //3) 同样提供静态方法获取实例
   //final就是防止别人来覆盖
   public static final SingletonDemo1 getInstance(){
       return LazyHolder.INSTANCE;
   }
}

饿汉式

/**
 * @ClassName SingletonDemo2
 * @Description 懒汉式单例,第一次调用时实例化
 * @Autuor lulinfeng
 * @Date 2020/9/17
 * @Version 1.0
 */
public class SingletonDemo2 {

    //第一步,构造函数私有化,在反射面前无用
    private SingletonDemo2() {
    }

    //第二步,声明一个final静态变量来保存单例的引用
    private static final SingletonDemo2 singletonDemo2 = new SingletonDemo2();

    //第三步,通过提供静态方法来获取单例的引用
    public static SingletonDemo2 getInstance() {
        return singletonDemo2;
    }
}

枚举

public enum SingletonDemo3 {
    INSTANCEW;
    public void getInstance(){}
}

登记式单例

/**
 * @ClassName Singleton4
 * @Description TODO
 * @Autuor lulinfeng
 * @Date 2020/9/17
 * @Version 1.0
 */
public class Singleton4 {
    private static Map<String, Singleton4> map = new HashMap<>();

    static {
        Singleton4 singleton4 = new Singleton4();
        map.put(singleton4.getClass().getName(), singleton4);
    }

    private Singleton4() {
    }

    public static Singleton4 getInstance(String name) {
        if (name == null) {
            name = Singleton4.class.getName();
        }
        if (map.get(name) == null) {
            try {
                map.put(name, (Singleton4) Class.forName(name).newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值