23种单例模式(单例模式)

单例模式

概念:

单个实例

使用场景:

比如当前写了个系统,在系统里有一些的通用配置,我们通常会把通用的配置都放在一个(config)类中.

当我们给系统写一些功能的时候,就需要实例化config类然后才可以添加通用的配置,那么我在新增功能或者修改功能的时候也需要同样的步骤,这样重复的实例化就会重复的开辟空间是十分浪费资源的,那么这个时候单例模式就有他的优势了,在系统中,单例模式可以使得某个类的实例有且只有一个,无论它创建了多少次对象

表现:

在系统中,某个类的实例有且只有一个,无论它创建了多少次对象

通俗来说:不管你实例化多少次,它始终只返回第一次创建的对象。不管你什么时候创建,它始终返回这一个对象.

优点:

在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。

避免对资源的多重占用(比如写文件操作)。

缺点:

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

具体步骤(不考虑多线程环境):

私有化构造方法: 禁止在外界使用new来创建对象

提供静态属性来返回当前类的唯一实例(类加载时创建,有且只有一份)

提供一个公开,静态的方法来返回当前类的唯一实例

分类:

饿汉模式: 积极创建策略,类加载时就会创建唯一实例

懒汉模式: 延迟创建策略,当需要创建实例时才创建


通过上面对单例模式的基本了解我们来通过代码实现一下:

Demo01:饿汉模式

public class SingletonDemo {
  /**提供静态属性返回当前对象实例*/
     private static SingletonDemo demo = new SingletonDemo();//饿汉模式单例(积极创建)
  
  /**私有化构造方法 -- 不让外界来使用new创建对象*/
    private SingletonDemo(){

    }
  
  /*提供一个公开静态的方法,返回当前对象的唯一实例*/
  public static SingletonDemo getInstance(){
        return demo;
  }
} 

TestDemo01

public class TestSingletonDemo {
    public static void main(String[] args) {
//通过SingletonDemo类中提供的公开静态的方法来创建对象
        SingletonDemo demo1 = SingletonDemo.getInstance();
        SingletonDemo demo2 = SingletonDemo.getInstance();
        System.out.println(demo1 == demo2);
    }
}
结果:true
  代表demo01和demo02是相等的,减少了创建实例的个数,减少系统资源的消耗

Demo02:懒汉模式

public class SingletonDemo {
  /**提供静态属性返回当前对象实例*/
    private static SingletonDemo demo;//懒汉模式单例(延迟创建)
  
  /**私有化构造方法 -- 不让外界来使用new创建对象*/
    private SingletonDemo(){

    }
  
  /*提供一个公开静态的方法,返回当前对象的唯一实例*/
    public static SingletonDemo getInstance(){
        if(demo == null){
            demo = new SingletonDemo();
        }
        return demo;
    }
} 

TestDemo02

public class TestSingletonDemo {
    public static void main(String[] args) {
//通过SingletonDemo类中提供的公开静态的方法来创建对象
        SingletonDemo demo1 = SingletonDemo.getInstance();
        SingletonDemo demo2 = SingletonDemo.getInstance();
        System.out.println(demo1 == demo2);
    }
}
结果:true
  代表demo01和demo02是相等的,减少了创建实例的个数,减少系统资源的消耗

单例模式常见的使用场景

window 的控制面板、任务管理器、回收站
网站的计数器
应用程序的日志应用:log4j、slf4j、logkback
项目中配置文件的读取
线程池(管理多个线程):java 自带线程池
数据库连接池(管理多个数据库连接):c3po 等
文件系统

从以上使用场景我们可以看出 ,其实那些所谓的常用场景,只要写一次,后期就基本上不会去改动了。所以我们用得非常少,但为什么我们总是谈起单例模式呢,就是那些面试官总是问这些问题
在Java中,运行时类也就是Runtime类,被设计成是单例的饿汉式,spring 中的bean 和spring mvc 中的controller、service、dao层中通过@autowire的依赖注入对象默认都是单例的,使用单例的目的当然是节约内存节省资源。

posted @ 2022-03-19 18:14  JanoCode  阅读(102)  评论(0)    收藏  举报