第二条
:使用私有构造函数强化singleton属性
Singleton:只能实例化一次的类。通常用来代表那些本质上具有惟一性的系统组件。
Singleton的实现要把构造函数保持为私有的,并提供一个静态成员,一边用户能够访问该类唯一的实例。 有两种实现方式:
1. 公有静态成员是一个final域
public class Elvis{
public static final Elvis INSTANSE = new Elvis();
private Elvis(){
…
}
}
好处:组成类的成员的声明很清楚地表明了这个类是个singleton。性能上稍微领先。
2. 提供公有静态工厂方法
public class Elvis{
private static final Elvis INSTANSE = new Elvis();
private Elvis(){
…
}
public static Elvis getInstance(){
return INSTANCE;
}
…
}
好处:提供了灵活性:不改变API的前提下,允许改变想法,singleton or nonsingleton。如果想修改它的唯一性,则可以为每个调用该方法的线程返回一个唯一的实例。
总之,如果希望保留一点余地,则使用第二种方法。
final通常是指“只是无法改变的。”不想改变可能出于两个理由:设计或效率。
1.
final
数据
不变的编译时常量:必须是基本类型,并以
final表示。对这个常量进行定义时,必须对其进行赋值。一个static and final的字段只占据一段不能改变的存储空间。注意,带有恒定初值的final static基本类型全用大写字母命名,并字与字之间用下划线隔开。
对象引用恒定不变:一旦引用被初始化指向一个对象,它就无法改为指向另一个对象。然而,对象自身却是可以修改的,
必须在字段的定义处或者每个构造器中用表达式对
final进行赋值。
在参数列表中将参数指明为
final表示无法在方法中更改参数引用所指向的对象。
2.
final
方法
原因
1:处于设计考虑,把方法锁定,以防任何继承类修改它的含义。
原因
2:处于效率考虑,编译器将针对该方法的所有调用都转为内嵌调用。
类中所有的
private方法都隐式地指定为是final的。
3.
final
类
表明你不打算继承该类。
final类中的方法也都是final的。
|
为了使一个singleton类变成可序列化的(serializable),并维护singleton性,则必须提供一个readResolve方法。 否则,一个序列化的实例在每次反序列化的时候,都会导致创建一个新的实例。
private Object readResolve() throws ObjectStreamException{
return INSTANCE;
}
1.
序列化概念
Java
的对象序列化将那些实现了
serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全回复为原来的对象。这一过程可以通过网络进行,就是说序列化机制能弥补不同操作系统之间的差异。
利用对象序列化能实现“轻量级持久性”。通过将一个序列化对象写入磁盘,然后在重新调用程序时恢复该对象,就能够实现持久性的效果。之所以叫“轻量级”,对象必须在程序中显示地序列化和反序列化还原。
2.
为什么序列化
对象序列化主要为了支持两种特性:
a. Java的“远程方法调用”(
rmi),它使存活于其他计算机的对象使用起来就像使存活在本机上一样。当向远程对象发送消息时,需要通过对象序列化来传输参数和返回值。
b. Java Beans,使用一个
Bean时,一般时在设计阶段对它的状态信息进行配置。这种状态信息必须保存下来,并在程序启动时进行后期恢复。
3.
如何序列化
序列化通过
Serializable接口实现,要序列化一个对象,首先创建某些OutputStream对象,然后将其封装在一个ObjectOutputStream对象内。此时只需调用writeObject()即可将对象序列化,并将其发送给OutputStream。要将序列还原为对象,需要将一个InputStream封装在ObjectInputStream内,然后调用readObject()。我们获得的是一个引用,它指向一个向上转型的Object,所以必须向下转型才能直接设置它们。
|