美文网首页设计模式专题
设计模式-单例模式

设计模式-单例模式

作者: RUMyCola | 来源:发表于2022-08-30 09:59 被阅读0次

    设计模式-单例模式

    定义

    单例模式(singleton pattern)是确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点

    单例模式是创建型模式。

    分类

    1、饿汉式(饿汉和静态饿汉)

    2、懒汉式(线程安全要加锁)

    3、枚举式(注册)初始化即生成,饿汉式,可以保证不被反射机制和反序列化破坏,是借助JDK的特性,所以最官方、最权威、最稳定

    4、序列化单例模式(可以解决反序列化问题,但是内存开销依然很大)

    5、容器式单例模式(容器式单例模式适用于需要大量创建单例对象的场景,便于管理。但它是非线程安全的)

    6、threadLocal单例模式(不能保证其创建的对象是全局唯一的,但是能保证在单个线程中是唯一的,天生是线程安全的)

    总结

        单例模式可以保证内存中只有一个实例,减少了内存开销,还可以避免对资源的多重占用。

    单例模式的常见应⽤场景

    单例模式(Singleton)也叫单态模式,是设计模式中最为简单的⼀种模式,甚⾄有些模式⼤师都不称其为模式,称其为⼀种实现技巧,因为设计模式讲究对象之间的关系的抽象,⽽单例模式只有⾃⼰⼀个对象,也因此有些设计⼤师并把把其称为设计模式之⼀。

    好多没怎么使⽤过的⼈可能会想,单例模式感觉不怎么⽤到,实际的应⽤场景有哪些呢?以下,我将列出⼀些就在咱们周边和很有意义的单例应⽤场景。

    1. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你⾃⼰试试看哦~

    2. windows的Recycle Bin(回收站)也是典型的单例应⽤。在整个系统运⾏过程中,回收站⼀直维护着仅有的⼀个实例。

    3. ⽹站的计数器,⼀般也是采⽤单例模式实现,否则难以同步。

    4. 应⽤程序的⽇志应⽤,⼀般都何⽤单例模式实现,这⼀般是由于共享的⽇志⽂件⼀直处于打开状态,因为只能有⼀个实例去操作,否则内容不好追加。

    5. Web应⽤的配置对象的读取,⼀般也应⽤单例模式,这个是由于配置⽂件是共享的资源。

    6. 数据库连接池的设计⼀般也是采⽤单例模式,因为数据库连接是⼀种数据库资源。数据库软件系统中使⽤数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是⾮常昂贵的,因为何⽤单例模式来维护,就可以⼤⼤降低这种损耗。

    7. 多线程的线程池的设计⼀般也是采⽤单例模式,这是由于线程池要⽅便对池中的线程进⾏控制。

    8. 操作系统的⽂件系统,也是⼤的单例模式实现的具体例⼦,⼀个操作系统只能有⼀个⽂件系统。

    9. HttpApplication 也是单位例的典型应⽤。熟悉ASP.Net(IIS)的整个请求⽣命周期的⼈应该知道HttpApplication也是单例模式,所有的HttpModule都共享⼀个HttpApplication实例.

      总结以上,不难看出:

    单例模式应⽤的场景⼀般发现在以下条件下:

    (1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的⽇志⽂件,应⽤配置。

    (2)控制资源的情况下,⽅便资源之间的互相通信。如线程池等。

    单例模式优点:

    1、在内存中只有一个实例,减少了内存开销。

    2、可以避免资源的多重占用。

    3、设置全局访问点,严格控制访问。

    单例模式的缺点:

    1、没有接口,扩展困难

    2、如果要扩展单例对象,只有修改代码,没有其他途径。

    代码实例

    1.1、饿汉式单例模式:类加载时立即初始化,并且创建单例对象。它绝对线程安全,在线程还没出现就实例化了,不存在访问安全问题。但是会导致内存浪费. 1.2、饿汉式单例模式(静态代码块):同第一种,唯一不同就是多点逼格O .O 2.1懒汉式单例模式,添加synchronized关键字后,解决了传统懒汉模式的线程安全问题,但是每次都要获取锁,性能较低. 2.2懒汉式单例模式改进(双重检查锁):可以有效的提高运行效率,那么我们可不可以不使用锁? 2.3懒汉式单例模式改进(静态内部类):这种形式来兼顾饿汉式单例模式的内存浪费问题和 synchronized 的性能问题(完美的屏蔽了这两个缺点) ,它还可以防止被反射破坏单例机制.到目前为止,这种写法基本上已经是最牛的啦,,但是依然可以被反序列化破坏(逐渐开始杠精起来...) 3.1、枚举类单例模式(属于注册式单例模式的一种):初始化即生成,饿汉式,可以保证不被反射机制和反序列化破坏,是借助JDK的特性,所以最官方、最权威、最稳定,因此枚举式单例模式是《Effective java》书中推荐的一种单例模式实现方法。 3.2、容器式单例模式(属于注册式单例模式的第2种):适用于需要大量创建单例对象的场景,便于管理。但它是非线程安全的。 4、序列化单例模式:反序列化导致单例模式被破坏,加上readResolve方法,可以解决反序列化问题,但是内存开销依然很大. 5、线程单例实现ThreadLocal:不能保证其创建的对象是全局唯一的,但是能保证在单个线程中是唯一的,天生是线程安全的。这个方式适合一些特定场景.

    学习单例模式的知识重点总结

    1、私有化构造器

    2、保证线程安全

    单例模式可以保证内存里只有一个实例,减少了内存的开销,还可以避免对资源的多重占用。单例模式看起来非常简单,实现起来其实也非常简单,但是在面试中却是一个高频面试点。希望“小伙伴们”通过本章的学习,对单例模式有了非常深刻的认识,在面试中彰显技术深度,提升核心竞争力,给面试加分,顺利拿到录取通知(Offer)。

    扩展

    1、解决容器式单例的线程安全问题。

    两种方法:双重检查锁,利用ConcurrentHashMap#putIfAbsent()方法的原子性。

    public class ContainerSingleton {

        private static Map ioc = new ConcurrentHashMap();

        private ContainerSingleton() {

                throw new RuntimeException("不可被实例化!");

        }

        // 方法一:双重检查锁

        public static Object getInstance(String className) {

            Object instance = null;

            if (!ioc.containsKey(className)) {

                synchronized (ContainerSingleton.class) {

                    if (!ioc.containsKey(className)) {

                        try {

                            instance = Class.forName(className).newInstance();

                            ioc.put(className, instance);

                        } catch (Exception e) {

                            e.printStackTrace();

                        }

                    return instance;

                    } else {

                        return ioc.get(className);

                    }

                }

            }

            return ioc.get(className);

        }

        // 方法二:利用ConcurrentHashMap#putIfAbsent()方法的原子性

    public static Object getInstance1(String className){

        Object instance = null;

        try {

            ioc.putIfAbsent(className, Class.forName(className).newInstance());

        }catch (Exception e){

            e.printStackTrace();

        }

        return ioc.get(className);

        }

    }

    相关文章

      网友评论

        本文标题:设计模式-单例模式

        本文链接:https://www.haomeiwen.com/subject/thllnrtx.html