单例模式
单例模式只能有一个被自己创建的实例
饿汉式
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
//私有化构造方法
private EagerSingleton(){
}
public static EagerSingleton getInstance() {
return instance;
}
}
饿汉式模式的类的实例是在类初始化的时候就被创建了,不管被谁调用或者不被调用,都是该类初始化的时候创建的实例;私有化的构造方法是为了防止调用者去实例化新的对象;
懒汉式
public class LazySingleton {
private static LazySingleton instance = null;
// 私有化构造方法
private LazySingleton() {
}
public synchronized static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
懒汉式模式的类在类加载的时候并没有被初始化,而是等到第一次被获取的时候才初始化;私有构造同上;之所以获取实例的方法设置成同步,是因为要应对多线程;避免多线程同时访问创建出多个实例的情况;
饿汉懒汉对比
- 由于是私有化构造参数,多以单例模式的类都不能被继承;
- 理论上饿汉式会比懒汉式更占资源;
- 懒汉式首次调用实例方法会涉及到改类的初始化,当遇上多线程的时候,会比饿汉式慢;
登记式
package com.black.singleton;
import java.util.HashMap;
public class RegisterSingleton {
private static HashMap m = new HashMap<>();
static {
RegisterSingleton rs = new RegisterSingleton();
m.put(rs.getClass().getName(), rs);
}
//受保护的构造方法,方便被继承
protected RegisterSingleton(){
}
public static RegisterSingleton getIntance(String name) {
if(name == null) {
name = RegisterSingleton.class.getName();
}
if(m.get(name) == null) {
try {
m.put(name, Class.forName(name).newInstance());
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
System.out.println(e.getMessage());
}
}
return (RegisterSingleton) m.get(name);
}
}
package com.black.singleton;
public class RegisterSingletonChild extends RegisterSingleton {
//公开,让父类去实例化他
public RegisterSingletonChild() {
}
public static RegisterSingletonChild getIntance() {
return (RegisterSingletonChild) RegisterSingleton.getIntance(RegisterSingletonChild.class.getName());
}
}
登记式模式解决了饿汉式和懒汉式不能继承的问题;但是由于子类的构造方法是public的,所以有被创建新的对象的风险;