设计模式之单例模式
单例模式-即一个类只构造一个实例。并且提供一个方法访问该唯一的对象。
优点
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
缺点
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
饿汉式
在类加载的阶段,其实例就被初始化了。
优点
线程安全,加载完成后的调用效率高。
缺点
无法延迟加载,如果实例化类之后没有使用,就造成浪费。
class hunger{
private static hunger s=new hunger();
private hunger() {};
public static hunger getInstance() {
return s;
}
}
懒汉式
什么时候需要,什么时候加载。
优点
使用灵活,可以延迟加载。资源利用率高
缺点
每一次获取实例都要获取锁,并发效率低。
class lizzy{
private static lizzy s;
private lizzy() {};
public static synchronized lizzy getInstance() {
if(s==null) s=new lizzy();
return s;
}
}
##静态内部类模式
####实现方式
在静态内部类中实例化对象,
优点
调用效率高,线程安全,可以延迟加载
class inclass{
private static class in{
private static final inclass instance=new inclass();
}
private inclass() {};
public static lizzy getInstance() {
return inclass.instance;
}
}
##枚举方式
没写完----
别人的文章https://blog.csdn.net/yy254117440/article/details/52305175
####优点
因为枚举类天然就是线程安全。所以这种方法就天然是线程安全的。
效率高,但不能延时加载。
####实现方式
//定义单例模式中需要完成的代码逻辑
interface MySingleton {
void doSomething();
}
public enum inface implements MySingleton {
INSTANCE {
@Override
public void doSomething() {
System.out.println("complete singleton");
}
};
public static MySingleton getInstance() {
return inface.INSTANCE;
}
}
单例模式的破解
单例模式的五种实现方法中,除了通过enum的实现外,其它四种都可以通过序列化和反序列化或者反射进行破解。
###反射破解原理
通过获取类的Class对象,然后调用其私有构造器,从而多次实例化对象。
防止办法
在私有构造器中加入函数,使私有构造器只能调一次。
if(instance!=null){
throw new RuntimeException();
}
###序列化破解
如果单例类可以序列化,那么我们先把对象序列化到一个文件里,然后反序列化这个文件,那么会得到一个新的对象。
防止办法
为该类添加readResolve()方法。该方法基于回调,只要定义好了,反序列化时就一定会调用该方法。
//反序列化时会直接调用该方法返回之前对象,而不是新的对象。
private readResolve()throws Exception{
return instance;
}