- 大家好!欢迎莅临厚土燎原的天地,深感荣幸能与您相遇在此,共同品读我的拙作。您的阅读如同春风化雨,对我而言意义非凡。衷心邀请您留下宝贵的评论与指点,每一字一句都是对我莫大的鼓励与鞭策。热烈欢迎,期待与您智慧碰撞,共绘思想的火花!
- 🌿🌿🌿 个人主页:厚土燎原
目录
描述
单例模式(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