单例模式
概念:
单例模式保证了一个类仅有一个实例,并提供一个访问它的全局访问点。
常用案例:
Windows的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web应用的配置对象、应用程序中的对话框、系统中的缓存等
特点:
- 单例类只有一个实例对象;
- 该单例对象必须由单例类自行创建;
- 单例类对外提供一个访问该单例的全局访问点。
优点:
- 单例模式可以保证内存里只有一个实例,减少了内存的开销。 可以避免对资源的多重占用。
- 单例模式设置全局访问点,可以优化和共享资源的访问。
缺点
- 单例模式一般没有接口,不支持扩展,违背开闭原则。
- 在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
- 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。
实现形式:
1、饿汉式(类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在)
public class SingleObject {
//创建SingleObject的一个对象
private static SingleObject instance = new SingleObject();
//使用private修饰构造函数,避免该类被实例化
private SingleObject(){}
//提够一个获取唯一对象的方法
public static SingleObject getInstance() {
return instance
}
}
//饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。
2、懒汉式(类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例)
public class SingleObject {
private static SingleObject instance;
//private构造方法保证外部无法实例化
private SingleObject();
public static SingleObject getInstance() {
//访问该方法时,若instance未实例化则进行实例化
if(instance == null) {
instance = new SingleObject();
}
return instance;
}
}
懒汉式在多线程中是错误的,因为在竞争条件下会创造出多个实例,此时需要对整个方法进行加锁。
//对方法进行加锁,被锁的对象是当前类对象。该方式会严重影响并发性能。
public static synchronized SingleObject getInstance() {
//访问该方法时,若instance未实例化则进行实例化
if(instance == null) {
instance = new SingleObject();
}
return instance;
}