什么是单例,什么是多例
单例和多例主要是表示一个类创建对象的实例数量。这里的数量是指在JVM内存模型中的数量。
单例模式的创建思路
1、私有化构造器,使用private修饰符;--防止通过new创建实例。
2、提供静态的对象属性,并且私有化;--防止通过类名直接访问。
3、提供公有的get()获取方法。
简介
1、解决的问题:主要解决一个类只能有一个实例的应用场景问题。
2、类图:不涉及其他对象,无类图。唯一一种无类图的设计模式。
3、优点:让一个类产生对象只有唯一的一个,这样可以大量减少内存的消耗,节约资源。
4、缺点:滥用单例可能会带来负面影响,比如,采用单例模式创建数据库连接。在多线程访问下,可能导致线程A打开连接池,正准备连接数据库操作时,线程B将连接关闭。导致操作异常。
5、运用:
①、Spring中IOC容器不是单例的,但是由其创建维护的Bean对象均为单例模式;
②、SpringMVC中的controller默认也是单例模式。
③、servlet中也是运用的单例模式。
实现方式
1、饿汉式
特点:线程安全,调用效率高。但是,不能延时加载。
/**单例模式-立即加载*/
public class Man {
//静态的私有的对象属性
private static Man m=new Man();
//私有的构造方法,就不能在该类以外通过new的方式产生对象。
private Man(){}
//公有的get方法
public static Man getMan() {
return m;
}
}
2、懒汉式
特点:线程安全,调用效率不高。但是可以延时加载。
//延时加载,资源利用率高了,但是每次调用get方法都要同步,并发效率较低.
public class Man {
//静态的私有的对象属性
private static Man m;
//私有的构造方法,就不能在该类以外通过new的方式产生对象。
private Man(){}
//公有的get方法
public static synchronized Man getMan() {
if(m==null){
m=new Man();
}
return m;
}
}
3、静态内部类方式
特点:线程安全,调用效率高。并且可以延时加载。
/**单例模式-延迟加载*/
public class Man {
//私有的构造方法,就不能在该类以外通过new的方式产生对象。
private Man(){};
//静态匿名内部类
private static class ManStatic{
//创建对象
private static Man m= new Man();
}
public static Man getMan() {
return Man.ManStatic.m;
}
}
4、枚举式(调用方法:通过类名.INSTANCE获取单例对象)
特点:线程安全,调用效率高,并且可以天然的防止反射和反序列化漏洞。
/**立即加载*/
public enum Man {
//定义一个枚举元素,它就代表了Man的一个实例.
INSTANCE;
//单例可以有自己的操作,例:功能处理.属性及方法均可.
}
5、如何选用?
--单例对象 占用 资源少,不需要 延时加载:
枚举式 好于 饿汉式
--单例对象 占用 资源大,需要 延时加载:
静态内部类式 好于 懒汉式
扩展知识
1、struts 2、servlet、SpringMVC是多例还是单例。
struts 2实例为多例;servlet实例为单例模式;SpringMVC默认实例为单例模式;
2、单例模式与TreadLocal的结合使用。
个人总结;有什么错误的地方欢迎留言指正,如果觉得帮助到你的话请点个赞鼓励一下作者吧。
刚开始写,您们的支持就是我努力的最大动力。。。