设计模式之单例模式
一、单例模式
1.单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实列,并提供
一个全局访问点。
2.隐藏其所有的构造方法
3.属于创建型模式。
1. 学习单例模式应掌握什么?
1.掌握单例模式的应用场景
2.掌握IDEA环境下的多线程调试方式
3.掌握保证线程安全的单例模式策略
4.掌握反射暴力攻击单例解决方案及原理分析
5.序列化破坏单例的原理及解决方案
6.掌握常见的单例模式写法
2. 适用场景
1. 确保任何情况下都绝对只有一个实例
3.缺点
1. 没有接口,扩展困难
2. 如果要扩展单例对象,只有修改代码,没有其他途径
二、常见的单例模式写法
1.饿汉式单例
2.懒汉式单例
3.注册时单例
4.ThreadLocal单例
1. 饿汉式单例
public class HungryStaticSingleton {
private static final HungryStaticSingleton hungrySingleton;
static{
hungrySingleton = new HungryStaticSingleton();
}
public HungryStaticSingleton() {
}
public static HungryStaticSingleton getInstance(){
return hungrySingleton;
}
}
2. 懒汉式单例
1. 简单模式的懒汉式单例
public class LazySimpleSingleton {
private static LazySimpleSingleton instance;
public LazySimpleSingleton() {
}
public synchronized static LazySimpleSingleton getInstance(){
if(null == instance){
instance = new LazySimpleSingleton();
}
return instance;
}
}
2.内部类模式的懒汉式单例
public class LazyInnerClassSingleton {
private LazyInnerClassSingleton() {
if(LazyHolder.instance != null){
throw new RuntimeException("不能非法访问");
}
}
public static LazyInnerClassSingleton getInstance(){
return LazyHolder.instance;
}
private static class LazyHolder{
private static final LazyInnerClassSingleton instance = new LazyInnerClassSingleton();
}
}
3.双重检查模式的懒汉式单例
public class LazyDoubleCheckSingleton {
private volatile static LazyDoubleCheckSingleton instance;
public LazyDoubleCheckSingleton() {
}
public static LazyDoubleCheckSingleton getInstance(){
if(null == instance){
synchronized(LazyDoubleCheckSingleton.class){
if(null == instance) {
instance = new LazyDoubleCheckSingleton();
}
}
}
return instance;
}
}
3.注册式单例
1. 容器注册类似于spring ioc容器
public class ContainerSingleton {
public ContainerSingleton() {
}
private static Map<String, Object> ioc = new ConcurrentHashMap<>();
public static Object getInstance(String className){
Object instance = null;
if(!ioc.containsKey(className)){
try {
instance = Class.forName(className).newInstance();
ioc.put(className, instance);
} catch (Exception e) {
e.printStackTrace();
}
}else{
return ioc.get(className);
}
return instance;
}
}
public class ContainerSingletonTest {
public static void main(String[] args) {
Object instance1 = ContainerSingleton.getInstance("com.leo.singleton.register.ContainerSingleton");
Object instance2 = ContainerSingleton.getInstance("com.leo.singleton.register.ContainerSingleton");
System.out.println(instance1 == instance2);
}
}
3. 枚举单例
public enum EnumSingleton {
INSTANCE;
public Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static EnumSingleton getInstance(){
return INSTANCE;
}
}
4. ThreadLocal单例
public class ThreadLocalUser {
public static ThreadLocal<TokenUser> userInfo = new ThreadLocal<TokenUser>();
public ThreadLocalUser() {
}
public static TokenUser getUserInfo() {
return (TokenUser) userInfo.get();
}
public static void setUserInfo(TokenUser user) {
userInfo.set(user);
}
}
三、单例能够通过反序列化破坏,但是可以通过重写readResolve 方法实现
public class SerializableSingleton implements Serializable {
public static final SerializableSingleton instance = new SerializableSingleton();
public static SerializableSingleton getInstance(){
return instance;
}
private Object readResolve(){
return instance;
}
}