设计模式之单例模式

  •   大家好!欢迎莅临厚土燎原的天地,深感荣幸能与您相遇在此,共同品读我的拙作。您的阅读如同春风化雨,对我而言意义非凡。衷心邀请您留下宝贵的评论与指点,每一字一句都是对我莫大的鼓励与鞭策。热烈欢迎,期待与您智慧碰撞,共绘思想的火花!


目录

描述

实现方式

优点

缺点

应用场景

实例

饿汉式

懒汉式(线程不安全)

懒汉式(线程安全)

双重检查锁

静态内部类

枚举类

总结


描述

单例模式(Singleton Pattern)是一种常用的软件设计模式,用于确保一个类仅有一个实例,并提供一个全局访问点来获取该实例。单例模式的主要目的是确保一个类只有一个实例,并提供一个访问它的全局访问点,从而避免了类的多个实例之间的数据不一致性和额外的开销。

实质:一个类只有一个实例


实现方式

单例模式有多种实现方式,但主要分为懒汉式(线程不安全)、懒汉式(线程安全)、饿汉式、双重校验锁(Double-Check Locking)、静态内部类以及枚举单例等。


优点

1、控制资源访问:通过单例模式,可以全局控制对资源的访问,比如配置文件、数据库连接等,避免资源的多重占用和浪费。

2、简化管理:由于类控制了自己的实例化过程,所以可以避免在应用中多次创建同一类的实例,从而简化了管理。

3、减少内存开销:因为单例模式限制了类的实例个数,所以对于一些大型对象或消耗资源较多的对象,使用单例模式可以减少内存的开销。

4、提供全局访问点:单例模式通过提供一个全局访问点来访问唯一的实例,这在使用时非常方便,无需重复创建对象。

5、提高系统性能:在需要频繁创建和销毁对象但又消耗大量资源的场景下,使用单例模式可以避免这种开销,从而提高系统性能。


缺点

1、单例模式违反了单一职责原则:单一职责原则要求一个类应该仅负责一项职责,但单例模式将类的实例化过程封装在类内部,这可能会使得类的职责过重。

2、扩展性差:由于单例模式限制了类的实例化个数,所以在需要扩展时可能会遇到障碍,比如需要不同配置信息的实例时,单例模式就难以应对。

3、隐藏类的依赖关系:使用单例模式时,客户端代码与单例类的实例是紧密耦合的,这可能会隐藏类的依赖关系,导致代码难以理解和维护。

4、滥用可能导致问题:如果不恰当地使用单例模式,比如在每个类中都使用单例模式,那么可能会导致系统变得难以测试和维护。

5、单例的生命周期管理:单例的生命周期通常与应用程序的生命周期相同,这可能会导致一些资源无法及时释放,从而引发内存泄漏等问题。


应用场景

1、全局唯一的配置类。

2、访问全局唯一的数据库连接池。

3、计数器,如网站的访问量等。

4、缓存类,如线程池、数据库连接池等。

5、应用程序中的日志应用等。


实例

饿汉式

public class SingleTon {

    private static SingleTon singleTon = new SingleTon();

    private SingleTon(){
    }

    public static SingleTon getInstance(){
        return singleTon;
    }
}

饿汉式基于classloder机制避免了多线程的同步问题,但实例在类装载时就完成创建,没有达到lazy loading的效果。

懒汉式(线程不安全)

public class SingleTon {

    private static SingleTon singleTon;

    private SingleTon(){
    }

    public static SingleTon getInstance(){
        if(singleTon == null){
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}

这种实现方式在多线程环境下是不安全的

懒汉式(线程安全)

public class SingleTon {

    private static SingleTon singleTon;

    private SingleTon(){
    }

    public static synchronized SingleTon getInstance(){
        if(singleTon == null){
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}

虽然这种方法是线程安全的,但每次调用getInstance()时都是同步的,效率较低。

双重检查锁

public class SingleTon {

    private static SingleTon singleTon;

    private static Object lock = new Object();

    private SingleTon(){
    }

    public static synchronized SingleTon getInstance(){
        if(singleTon == null){
            synchronized (lock){
                if(singleTon == null){
                    singleTon = new SingleTon();
                }
            }
        }
        return singleTon;
    }
}

双重校验锁既实现了延迟加载,又保证了线程安全。

静态内部类

public class SingleTon {

    private SingleTon(){

    }

    private static class SingleTonHolder{
        private static SingleTon INSTANCE = new SingleTon();
    }

    public static SingleTon getInstance(){
        return SingleTonHolder.INSTANCE;
    }

}

这种方式利用了classloder的机制来保证初始化instance时只有一个线程,并且不需要进行额外的同步。

枚举类

public enum  SingleTon {

    INSTANCE;
    
    public void doSomething(){
        System.out.println("doSomething");
    }
}

枚举单例是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候,也能保证安全的单例。


总结

简述:保证一个类仅有一个实例,并且提供一个全局访问点

一句话概括:世上只有一个我

目的:保证独一无二

生活案例:CEO


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

厚土燎原

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值