开发模式)Note6)单例模式的实现
作者:互联网
内容均为网上收集整理,供自己学习做笔记使用
一,什么是单例模式
Java中的单例模式是一种非常常见的设计模式,单例模式的写法有很多种,本次主要实现懒汉、饿汉式单例,登记式单例。单例模式的特点有:
- 单例类只能有一个实例。
- 单例类必须自己来创建自己的唯一实例。
- 单例类必须要给所有其他对象提供这一实例。
单例模式确保每个类都只有一个实例,而且自行实例并向整个系统提供这个实例。在计算机系统中比如线程池、缓存、日志等对象常被设计称为单例的。单例模式的出现就是为了避免不一致的状态,避免政出多头。
二,懒汉式单例实现
package one.example;
/**
* 懒汉式单例类,在第一次调用的时候实例化自己
* @author ShadowY
*
* 2021年8月24日 下午6:56:08
*/
public class Singleton {
private Singleton() {};
private static Singleton singleton = null;
//静态工厂方法
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
Singleton将自己的构造方法限定为private的,这样可以避免类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例之鞥呢通过getInstance()方法来访问。(事实上这样做并不是绝对安全的,通过Java反射机制是可以实例化构造方法为private的类的,那基本会使所有的Java单例实现失效。)
上述的懒汉式单例模式并没有考虑到线程安全问题,在并发度较高的环境下,可能会出现不止一个的Singleton实例。
- 给getInstance()方法加上同步,保证同时间下只有一条线程能进来:
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
- 双重检查(其实还是同步):
public static synchronized Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
- 静态内部类
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
三,饿汉单例实现
package one.example;
/**
* 饿汉式单例类,在类进行初始化的时候,就会自行实例化
* @author ShadowY
*
* 2021年8月24日 下午7:37:56
*/
public class Singleton {
private Singleton() {}
private static final Singleton SINGLETON = new Singleton();
//静态工厂方法
public Singleton getInstance() {
return SINGLETON;
}
}
饿汉式在类创建的时候就已经创建好了一个静态的对象供我们使用,用final修饰表明后面不会再发生改变,通过这种方法可以不需要考虑线程安全的问题。
四,登记式单例
//类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton3 {
private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保护的默认构造子
protected Singleton3(){}
//静态工厂方法,返还此类惟一的实例
public static Singleton3 getInstance(String name) {
if(name == null) {
name = Singleton3.class.getName();
System.out.println("name == null"+"--->name="+name);
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton3) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
//一个示意性的商业方法
public String about() {
return "Hello, I am RegSingleton.";
}
public static void main(String[] args) {
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}
五,实际应用
package one.example;
/**
* 懒汉式单例类
* @author ShadowY
*
* 2021年8月24日 下午7:47:03
*/
public class Singleton {
String name = null;
private Singleton(){}
private static volatile Singleton singleton = null;
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void printInfo() {
System.out.println("the name is " + name);
}
}
package one.example;
/**
* Singleton类的测试类
* @author ShadowY
*
* 2021年8月24日 下午7:48:51
*/
public class SingletonTest {
public static void main(String[] args) {
Singleton st1 = Singleton.getInstance();
st1.setName("I'am ST1");
Singleton st2 = Singleton.getInstance();
st2.setName("I'am ST2"); //ST1与ST2其实是一个实例,调用的其实是一个实例,会覆盖之前的
st1.printInfo();
st2.printInfo();
if (st1==st2) {
System.out.println("st1和st2其实是一个实例");
}else {
System.out.println("st1和st2是两个不同的实例");
}
}
}
//the name is I'am ST2
//the name is I'am ST2
//st1和st2其实是一个实例
总结:单例模式为一个面向对象的应用程序提供了对象唯一的访问点,无论实现何种功能,整个应用程序都会共享用一个实例对象。对于这两种实现方式,要知道饿汉式与懒汉式的区别、线程安全、资源加载的实际以及懒汉式实现线程安全的方式。
标签:Singleton,name,singleton,模式,Note6,static,单例,public 来源: https://blog.csdn.net/zy_zhangruichen/article/details/119896801