• 设计模式学习笔记——单例模式


    定义

    单例模式(Singleton Pattern)是一个比较简单的模式,其定义如下:Ensure a class has only one instance, and provide a globalpoint of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)

    通用代码

    public class Singleton {
        private static final Singleton instance = new Singleton();
    
        // 限制产生多个对象
        private Singleton() {}
    
        // 通过该方法获得实例对象
        public static Singleton getInstance() {
            return instance;
        }
    
        public static void doSomething() {
        }
    }

    优点

    • 在内存中只有一个实例,不必频繁创建销毁,节约时空。
    • 避免对资源的多重占用
    • 可以在系统设置全局的访问点

    缺点

    • 一般没有接口,扩展很困难
    • 在并行开发环境中,如果单例模式没有完成,是不能进行测试的
    • 单例模式与单一职责原则有冲突

    使用场景

    在一个系统中,要求一个类有且仅有一个对象,如果出现多个对象就会出现“不良反应”,可以采用单例模式。

    饿汉式和懒汉式

    上述通用代码为“饿汉式单例”,在一开始便初始化instance。还有一种“懒汉式单例”,在首次调用getInstance时初始化对象,但在高并发的情况下会出现线程同步问题,产生两个instance,方法是加入关键字synchronized。

    实现代码如下:

    public class Singleton {
        private static Singleton instance = null;
    
        // 限制产生多个对象
        private Singleton() {}
    
        // 通过该方法获得实例对象
        public static synchronized Singleton getInstance() {
            if(instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    
        public static void doSomething() {
        }
    }

    注意事项

    如果我们的一个单例对象在内存中长久不使用,JVM就认为这个对象是一个垃圾,在CPU资源空闲的情况下该对象会被清理掉,下次再调用时就需要重新产生一个对象。如果我们在应用中使用单例类作为有状态值(如计数器)的管理,则会出现恢复原状的情况,应用就会出现故障。如果确实需要采用单例模式来记录有状态的值,可以使用Spring框架中的bean让对象长久驻留内存。

    其他探究

    饿汉式在类装载时就会加载对象,而懒汉式每次进入getInstance方法都需要同步,浪费了许多判断时间。有没有一种实现方法能够同时改进这两个缺点呢?

    我们可以利用JVM里的内部类来实现,保证线程安全性。代码如下:

    public class Singleton {
    
        // 静态的成员式内部类,只有被调用到时才会加载
        private static class SingletonHolder {
            private static Singleton instance = new Singleton();
    
        }
    
        // 私有化构造方法
        private Singleton() {}
    
        public static Singleton getInstance() {
            return SingletonHolder.instance;
        }
    
        public static void doSomething() {
    
        }
    }
  • 相关阅读:
    C++11新特性
    Qt操作xml
    指针和引用的区别
    QT软件主题切换
    常见的临时变量的生成场景
    QQuickWidget+QML设置背景透明
    idea maven Could not transfer artifact
    Java项目启动时执行指定方法的几种方式
    解决bootstrap-table在切换分页后再次查询报错404问题
    bootstrap:表单必填项*标识,及提交前校验
  • 原文地址:https://www.cnblogs.com/kunsoft/p/13675291.html
Copyright © 2020-2023  润新知