要求: 写一个java单例,类外部的代码无法创建其实例对象(反射机制也不能),即无法通过反射机制破坏单例的“唯一性”
【方案一】:
interface Allowed{
//用以定义允许单例类外部使用的接口:
void allowedOperation();
}
public class SafeSingletonShell{
/*
* 单例类的保护壳,用来防止通过反射机制破坏单例的“单”原则
*/
public static Allowed OnlyGiveWhatIWantTo(){
return RealSingleTon.instance;
}
public static Allowed getInstance() {
return OnlyGiveWhatIWantTo();
}
private static class RealSingleTon implements Allowed{
private static RealSingleTon instance = new RealSingleTon();
@Override
public void allowedOperation() {
// do some operation here:
System.out.println("safe op");
}
public void notAllowedOperation() {
// codes outside WeirdSingleton can not see
System.out.println("unsafe op");
}
public RealSingleTon getInstance() {
return instance;
}
}
}
class Tester{
/*
* 测试
*/
public static void main(String[] args) {
Allowed allowed = SafeSingletonShell.OnlyGiveWhatIWantTo();
allowed.allowedOperation();
//一下两行代码尝试创建另一个实例,但是无法编译通过:
//SafeSingletonShell.RealSingleTon realSingleTon = new SafeSingletonShell.RealSingleTon();
//realSingleTon.notAllowedOperation();
}
}
【方案二】
//注意到这是一个抽象类
abstract class SafeSingleTon3 {
public abstract void operation();
private static final SafeSingleTon3 INSTANCE;
static{
//防止第二次实例化
INSTANCE = new SafeSingleTon3() {
String f1;
@Override
public void operation() {
System.out.println("op done....");
}
};
}
public static Object getInstance() {
return INSTANCE;
}
}
如更好的方法请不要吝啬~
另外,如何防止通过序列化或自定义类加载器生成第二个实例、如何防止反编译生需要进一步讨论
目前已知的部分解决方法有:http://segmentfault.com/a/1190000000699591