「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
相关文章
设计模式系列:设计模式
前言
- 单例模式(Singleton) ,也叫单子模式,是一种常用的设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候,整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,显然,这种方式简化了在复杂环境下的配置管理。
- 单例模式就是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种方法。
- 平时我们使用的Spring中的Bean默认就是单例的!尤其是javaConfig!
一、饿汉单例
- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20- java复制代码//饿汉单例模式 
 @Data
 @Accessors(chain = true)
 public class ehanSingleton {
 //其他的属性,举例用的
 private Integer readings = 0;//阅读量
 private Integer collects = 0;//收藏量
 private Integer likes = 0;//点赞量
 
 //将自身的实例化对象设置成一个属性,并且加上final,static关键字修饰
 private static final ehanSingleton singleton = new ehanSingleton();
 
 //构造方法私有化---外部无法靠new来创建该对象
 private ehanSingleton(){};
 
 //公共的静态方法返回该实例,方便外部调用
 public static ehanSingleton getInstance(){
 return singleton;
 }
 }
- TestMain 
+ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
csharp复制代码public class SingletonMain {
    public static void main(String[] args) {
        ehanSingleton singleton = ehanSingleton.getInstance();
        singleton.setReadings(singleton.getReadings()+1);
        read(singleton);
        singleton.setCollects(singleton.getCollects()+1);
        singleton.setLikes(singleton.getLikes()+1);
        System.out.println("阅读量为:"+singleton.getReadings());
        System.out.println("收藏量为:"+singleton.getCollects());
        System.out.println("点赞量为:"+singleton.getLikes());
    }
    public static void read(ehanSingleton singleton){
        for (int i=0;i<100;i++){
            singleton.setReadings(singleton.getReadings()+1);
        }
    }
}
- 执行结果
+ - 一上来就把单例对象创建出来了,要用的时候直接返回即可,这种可以说是单例模式中最简单的一种实现方式。
- 但是问题也比较明显。单例在还没有使用到的时候,初始化就已经完成了。
- 也就是说,如果程序从头到位都没用使用这个单例的话,单例的对象还是会创建。这就造成了不必要的资源浪费。所以不推荐这种实现方式。
二、懒汉单例
- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36- java复制代码//懒汉单例模式 
 @Data
 public class lanhanSingleton {
 //其他的属性,举例用的
 private Integer readings = 0;//阅读量
 private Integer collects = 0;//收藏量
 private Integer likes = 0;//点赞量
 
 //将自身的实例化对象设置成一个属性,并且加上final,static关键字修饰
 private static lanhanSingleton singleton = null;
 
 //构造方法私有化---外部无法靠new来创建该对象
 private lanhanSingleton(){};
 
 //公共的静态方法返回该实例,方便外部调用,线程安全的1:同步代码块,效率低
 public static synchronized lanhanSingleton getInstance(){
 if (singleton == null){
 singleton = new lanhanSingleton();
 }
 return singleton;
 }
 
 //公共的静态方法返回该实例,方便外部调用,线程安全的2:DCL 双检查锁机制
 public static lanhanSingleton getInstance1(){
 synchronized(lanhanSingleton.class){
 //第一次检查instance是否被实例化出来,如果没有进入if块
 if (singleton == null){
 // 某个线程取得了类锁,实例化对象前第二次检查instance是否已经被实例化出来,如果没有,才最终实例出对象
 if (singleton == null){
 singleton = new lanhanSingleton();
 }
 }
 }
 return singleton;
 }
 }
- TestMain 
+ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
csharp复制代码public class SingletonMain {
    public static void main(String[] args) {
        lanhanSingleton instance = lanhanSingleton.getInstance();
        instance.setReadings(instance.getReadings()+1);
        read(instance);
        instance.setCollects(instance.getCollects()+1);
        instance.setLikes(instance.getLikes()+1);
        System.out.println("阅读量为:"+instance.getReadings());
        System.out.println("收藏量为:"+instance.getCollects());
        System.out.println("点赞量为:"+instance.getLikes());
    }
    public static void read(lanhanSingleton singleton){
        for (int i=0;i<100;i++){
            singleton.setReadings(singleton.getReadings()+1);
        }
    }
}
- 执行结果
+ - 线程安全,调用效率不高,但是能延时加载。
- 那么饿汉和懒汉在我们实际使用中该如何选择呢?
+ 单例对象 占用资源少,不需要延时加载,枚举 好于 饿汉
+ 单例对象 占用资源多,需要延时加载,静态内部类 好于 懒汉式路漫漫其修远兮,吾必将上下求索~
如果你认为i博主写的不错!写作不易,请点赞、关注、评论给博主一个鼓励吧~hahah
本文转载自: 掘金