对于系统的一些功能组件,有一个即可,例如数据库连接池,线程池。。。全局唯一。想要控制住对象的创建就用到了单例模式。
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
实现单例模式的步骤:
1、构造方法私有化,不让外部类创建对象,内部创建好,赋值给变量。
2、对外提供一个方法访问内部创建好的对象。
单例根据创建时机又分为两种:(1)懒汉模式,非线程安全 (2)饿汉模式
具体实现方式如下:
饿汉式:
1、class Single1{
public static final Single1 INSTANCE = new Single1();
private Single1(){
}
}
2、推荐,可以防止反射攻击
enum Single2{
INSTANCE;
}
3、
class Single3{
private static final Single3 INSTANCE = new Single3();
private String info;//需要在创建实例对象时,读取配置文件信息,为这个实例变量初始化
private Single3(){
Properties pro = new Properties();//集合,key和value都是String类型
try {
pro.load(new FileInputStream("info.properties"));//默认在项目根目录
} catch (IOException e) {
e.printStackTrace();
}
info = pro.getProperty("info");
}
//用来返回INSTANCE
public static Single3 getInstance(){
return INSTANCE;
}
}
懒汉式:
1、class Single4{
private static Single4 instance;//这里没有创建
private Single4(){ }
public static Single4 getInstance(){
if(instance == null){ //并不是每次进入方法都需要同步
synchronized (Single4.class) {
if(instance == null){ //空的时间创建
instance = new Single4();
}
}
}
return instance;
}
}
2、内部类实现
class Single5{
private Single5(){}
public static Single5 getInstance(){
return Inner.INSTANCE;
}
private static class Inner{
static final Single5 INSTANCE = new Single5();
}
}
最后,思考如何方式反射攻击?(通过反射获取构造函数,然后调用setAccessible(true)就可以调用私有的构造函数)
JDK1.5之后推荐枚举方式,可以有效防止反射攻击。