java单例注册表_设计模式-单例模式(Singleton)

单例模式的特征:

1.单例类只能有一个实例

2.单例类必须自己创建自己的实例

3.单例类必须给其他类提供这一实例

意图:保证一个类只有一个实例,并提供一个访问它的全局访问点

主要解决:一个全局使用的类频繁地创建与销毁

何时使用:需要控制实例数目,节省系统资源

如何解决:判断系统是否已经有这个实例,如果有则返回;如果没有则创建再返回

关键代码:构造函数是私有的

通过网上资料查询,得到单例模式的6种实现方式:

第一种

package com.yuxx.singleton;

/**

* 懒汉式:懒加载、线程不安全

* 由于没有加锁,严格意义上不算单例模式

*/

public class Singleton1 {

private static Singleton1 instance;

private Singleton1(){}

public static Singleton1 getInstance(){

if(instance == null){

instance = new Singleton1();

}

return instance;

}

}

第二种

package com.yuxx.singleton;

/**

* 懒汉式,懒加载,线程安全

* 优点:第一次调用才初始化,避免内存浪费

* 缺点:必须加锁synchronized才能保证单例,但加锁会影响效率

* 加锁后,相当于同一个时间,只能有一个线程来访问,就降低了并发性

*/

public class Singleton2 {

private static Singleton2 instance;

private Singleton2(){}

public static synchronized Singleton2 getInstance(){

if(instance == null){

instance = new Singleton2();

}

return instance;

}

}

第三种

package com.yuxx.singleton;

/**

* 饿汉式,非懒加载,线程安全

* 优点:没有加锁,执行效率提高

* 缺点:类加载时就初始化,浪费内存,容易产生垃圾对象

*/

public class Singleton3 {

private static Singleton3 instance = new Singleton3();

private Singleton3(){}

public static Singleton3 getInstance(){

return instance;

}

}

第四种

package com.yuxx.singleton;

/**

* 懒加载:线程安全

* 这种方式采用双锁机制,安全且在多线程情况下保持高性能。

*/

public class Singleton4 {

private volatile static Singleton4 instance;

private Singleton4(){}

public static Singleton4 getInstance(){

if(instance == null){

synchronized (Singleton4.class){

if(instance == null){

instance = new Singleton4();

}

}

}

return instance;

}

}

第五种

package com.yuxx.singleton;

/**

* 登记式/静态内部类:懒加载、线程安全

* 在这个方式中,Singleton5类被加载时,instance不会被实例化。因为instance是在SingletonHolder中被实例化。

* 只有在SingletonHolder也被显示装载使用时,才会得到Singleton5的实例。

* 如果实例化Singleton很消耗资源,所以想让它延迟加载,另一方面,又不希望Singleton5类被加载时就实例化,

* 因为不能确保Singleton类还可能在其他地方被主动使用而被加载,那么这个时候,这种方式相比第三种更合理。

*/

public class Singleton5 {

private static class SingletonHolder{

private static final Singleton5 INSTANCE = new Singleton5();

}

private Singleton5(){}

private static final Singleton5 getInstance(){

return SingletonHolder.INSTANCE;

}

}

第六种

package com.yuxx.singleton;

/**

* 枚举:非懒加载、线程安全

* 这个实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。

* 它更简洁,自动支持序列化机制,绝对防止多次实例化。

*/

public enum Singleton6 {

INSTANCE;

public void whateverMethod(){

System.out.println("do everything...");

}

}

关于第六种,我在学习的时候也有疑惑,不能理解枚举类和单例模式甚至实例之间有什么关系。后来通过网上各位前辈整理的资料得知,枚举类在编译后,实质上是一个继承了Enum类的class。因为我暂时没有找到可以查看到这种效果代码的方法,所以引用了前辈们的代码:

原枚举类:

public enum Type {

SELECT, UPDATE, INSERT, DELETE

};

反编译后:

public static final class Type extends Enum{

public static final Type SELECT;

public static final Type UPDATE;

public static final Type INSERT;

public static final Type DELETE;

private static final Type $VALUES[];

public static final Type[] values(){

return (Type[])$VALUES.clone();

}

public static Type valueOf(String name){

return (Type)Enum.valueOf(com/***/***/***/***$Type, name);

}

static {

SELECT = new Type("SELECT", 0);

UPDATE = new Type("UPDATE", 1);

INSERT = new Type("INSERT", 2);

DELETE = new Type("DELETE", 3);

$VALUES = (new Type[] {

SELECT, UPDATE, INSERT, DELETE

});

}

private Type(String s, int i){

super(s, i);

}

}

通过上面的代码,我们可以看出,其实原枚举类Type里的SELECT、UPDATE、INSERT、DELETE这四个元素,本质上就是普通类Type类的四个静态成员变量,类型是Type,并在静态块中被进行了实例化。而且Type类的构造方法被私有化了,这样就避免了被外来类调用并实例化的问题。(关于枚举类的原理,以后再学习进行总结)

而且,在枚举类中,也可以像普通类中去定义普通的成员变量和成员方法,类似这样:

enum Color{

RED,GREEN,BLUE;

private int code;

Color(int code){

this.code=code;

}

public int getCode(){

return code;

}

}

这样,我们普通类可实现的功能,枚举类也可以去实现了。

------------------------以下补充-----------------------

感谢若水提醒,此处补充下Spring中单例的实现:

Spring单例的定义方式可取决于Spring bean的装载方式:spring配置文件 or SpringBean配置类

1.spring配置文件

bean标签有个属性:scope,属性值则表明了这个bean是单实例还是多实例,单实例Singleton,多实例:prototype。没有这个属性值则默认是单实例

2.Bean配置类(Spring注解驱动了解到的)。

此处用的是Spring的@Scope注解,如果没有标明实例方式,也默认是单实例

@Scope("singleton")

@Bean("person")

public Person person(){

System.out.println("向容器中添加Person...");

return new Person("张三",25);

}

@若水的提问,Spring单例使用的上面哪种方式。

单例模式的常用场景,总体来说包括两种:

1.资源共享:例如系统中的应用配置文件的实例,还有一些公用的组件实例

2.通信控制:例如数据库连接池,为避免在使用中频繁打开连接和断开连接会降低整体功能的效率,而使用单例,一次打开,多次使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值