Item 3 ------单例模式的几种实现方式,及优缺点
2015-03-21 10:41 ttylinux 阅读(340) 评论(0) 收藏 举报单例模式,是指一个类只有一个唯一的实例,一个类只会被实例化一次。实现这种效果,最佳的方式,编写包含单个元素的枚举类型。
单例模式的最佳实现方式-----创建一个包含单个元素的枚举类
public enum Elvis {
ONE_INSTANCE;
public void leaveTheBuilding() {
System. out.println("Whoa baby, I'm outta here!" );
}
}
----------------------------------
public class Test {
public static void main(String[] args) {
Elvis elvis = Elvis. ONE_INSTANCE;
elvis.leaveTheBuilding();
}
}
优点就是:无偿提供了序列化机制,绝对防止多次实例化,解决每次反序列化一个实例化时,再次创建一个心的实例的问题;并且处理了发射攻击(用户通过反射机制,调用了私有构造器,从而打破只有一个实例的规定).
缺点:Java 1.5开始才支持。
通过一个公有的静态成员来实现--唯一的实例,是一个公有的静态成员
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {
}
public void leaveTheBuilding() {
System. out.println("Whoa baby, I'm outta here!" );
}
// This code would normally appear outside the class!
public static void main(String[] args) {
Elvis elvis = Elvis. INSTANCE;
elvis.leaveTheBuilding();
}
}
缺点:1.存在反射攻击缺陷。要抵御反射攻击,就要记录创建实例的个数,使用一个静态的类成员来保存。当实例个数超过1时,发出异常。2.在序列化一个类时,要添加方法readResolve。添加该方法的目的是,避免每次在反序列化的时候创建一个新的实例。
优点:它的表现简洁明了。
通过公有的静态工厂方法
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() {
}
public static Elvis getInstance() {
return INSTANCE ;
}
public void leaveTheBuilding() {
System. out.println("Whoa baby, I'm outta here!" );
}
// This code would normally appear outside the class!
public static void main(String[] args) {
Elvis elvis = Elvis. getInstance();
elvis.leaveTheBuilding();
}
}
优点:
将API与实现隔绝开,客户端只管调用getInstance()方法,不管该方法是怎么实现的。如此,你就可以修改getInstance()的实现,而不用考虑客户端是怎么使用的。
比如,它可以被修改为,并不是返回一个唯一的实例;或者修改为,每个线程有一个唯一的实例,在某个线程范围内,该类的实例是唯一的。
缺点:
1.存在反射攻击缺陷。要抵御反射攻击,就要记录创建实例的个数,使用一个静态的类成员来保存。当实例个数超过1时,发出异常。
2.在序列化一个类时,要添加方法readResolve。添加该方法的目的是,避免每次在反序列化的时候创建一个新的实例。
解决缺点2的做法:
添加一个readResolve()方法。
public class Elvis implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final Elvis INSTANCE = new Elvis();
private String one;
private Elvis() {
}
public void leaveTheBuilding() {
System. out.println("Whoa baby, I'm outta here!" );
}
private Object readResolve() {
// Return the one true Elvis and let the garbage collector
// take care of the Elvis impersonator.
return INSTANCE ;
}
// This code would normally appear outside the class!
public static void main(String[] args) {
Elvis elvis = Elvis. INSTANCE;
elvis.leaveTheBuilding();
}
}
版权声明:
作者:ttylinux
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
浙公网安备 33010602011771号