设计模式——单例模式

119 阅读3分钟

一、定义

确保一个类有且仅有一个实例,且自行化实例,并向整个系统提供这个实例。

二、通用代码

public class singleClass{
    private static final SingleClass single = new SingleClass(); 
    private SingleClass(){
        //构造函数 
    }
    public static SingleClass getInstance(){ 
        //对外提供实例
        return single; 
    } 
    public static void doSomethings(){ 
        //其他类
    } 
}

三、优点

  1. 减少内存开支,特别是当一个类需要频繁创建、销毁时
  2. 减少系统的性能开销
  3. 避免资源的多重占用
  4. 可以设置全局访问点,优化和共享资源访问

四、缺点

  1. 不可扩展(也可以说是违反了开闭原则)
    • 例模式一般不为接口
    • 单例模式要求自行实例化且提供单一实例,然而接口和抽象类不可能被实例化,因此接口和抽象类对单例模式来说,没有任何意义
  2. 对测试不利,主要是并行开发中,如果单例类未完成,其他方法无法进行测试
  3. 与单一职责原则冲突。
    • 单一职责要求只能有一个原因引起类的变更,即一个类只实现一个逻辑
    • 但是单例类则会将多个业务逻辑整合在一个类中

五、应用场景

  1. 生产唯一序列号
  2. 项目中需要一个共享访问点或共享数据
  3. 创建一个对象需要消耗的资源过多。如访问IO和数据库
  4. 定义大量的静态常量和静态方法(当然这个也可以采用static来操作)

六、注意事项

  1. 线程不安全。第一次调用才进行实例化,即初始化对象为null,getInstance()中设定初始对象为null,则创建对象,否则返回现有的对象(代码如下文)。但是在高并发中,很容易出现对象还在创建,新线程就过来,发现对象仍为null,则会继续创建新对象,则单例会被破坏。
    public class singleClass{ 
        private static final SingleClass single = null; 
        private SingleClass(){ 
            //构造函数
        } 
        public static SingleClass getInstance(){
            //对外提供实例
            if(single == null){
            single = new SingleClass(); 
            } 
            return single; 
        } 
        public static void doSomethings(){
            //其他类
        }
    }
    
    为避免这种情况,可在getInstance()方法前加Synchronized关键字
  2. 对象复制会跳过构造方法,导致产生多个对象。但是这种一般不需要管,一般单例类的也不会主动被复制

七、实现方式

该段内容来自一文搞懂设计模式—单例模式 掘金 (juejin.cn)代码和讲解太好了,我就不班门弄斧了,想看实现代码的直接去这篇文章看吧

实现方式优点缺点
饿汉式线程安全;简单直接;性能高不能懒加载,会占用一定资源
懒汉式迟加载,避免不必要的资源消耗线程不安全;需要判断和创建,性能会有所影响
双重校验锁线程安全的懒汉式变种/未知
静态内部类线程安全的懒汉式变种/未知
枚举式线程安全;防止反射工具和序列化破坏;简介明了/未知

八、扩展

设计固定数量的对象。也被称作有上限的多例模式。即在实例化时,直接实例多个单例对象