您的位置:首页 > 其它

Item 3 ------单例模式的几种实现方式,及优缺点

2015-03-21 10:41 465 查看
单例模式,是指一个类只有一个唯一的实例,一个类只会被实例化一次。实现这种效果,最佳的方式,编写包含单个元素的枚举类型。

单例模式的最佳实现方式-----创建一个包含单个元素的枚举类

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();
}
}


[align=left]优点就是:无偿提供了序列化机制,绝对防止多次实例化,解决每次反序列化一个实例化时,再次创建一个心的实例的问题;并且处理了发射攻击(用户通过反射机制,调用了私有构造器,从而打破只有一个实例的规定).[/align]
[align=left]缺点:Java 1.5开始才支持。[/align]
[align=left] [/align]

[align=left]通过一个公有的静态成员来实现--唯一的实例,是一个公有的静态成员[/align]

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();
}
}


[align=left]缺点:1.存在反射攻击缺陷。要抵御反射攻击,就要记录创建实例的个数,使用一个静态的类成员来保存。当实例个数超过1时,发出异常。2.在序列化一个类时,要添加方法readResolve。添加该方法的目的是,避免每次在反序列化的时候创建一个新的实例。[/align]
[align=left]优点:它的表现简洁明了。[/align]
[align=left] [/align]
[align=left]通过公有的静态工厂方法[/align]
[align=left] [/align]

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();
}
}


[align=left]优点:[/align]
[align=left]将API与实现隔绝开,客户端只管调用getInstance()方法,不管该方法是怎么实现的。如此,你就可以修改getInstance()的实现,而不用考虑客户端是怎么使用的。[/align]
[align=left]比如,它可以被修改为,并不是返回一个唯一的实例;或者修改为,每个线程有一个唯一的实例,在某个线程范围内,该类的实例是唯一的。[/align]
[align=left] [/align]
[align=left]缺点:[/align]
[align=left]1.存在反射攻击缺陷。要抵御反射攻击,就要记录创建实例的个数,使用一个静态的类成员来保存。当实例个数超过1时,发出异常。[/align]
[align=left]2.在序列化一个类时,要添加方法readResolve。添加该方法的目的是,避免每次在反序列化的时候创建一个新的实例。[/align]

[align=left]解决缺点2的做法:[/align]
[align=left]添加一个readResolve()方法。[/align]

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();
}
}


  

[align=left] [/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: