一 静态工厂代替构造方法
static factory method 是一个返回类实例的静态方法
来看看jdk的boolean类的封装
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
优势
- 有不同的名称
- 不必每次调用都创建一个新的对象
- 可以返回原对象的任何子集
- 参数对象实例时代码更加简洁
二 用私有构造器/枚举强化Singleton属性
Singleton 指仅仅实例化一次的类 , Singleton通常代表唯一的系统组件 , 比如窗口管理 / 文件系统 . 使类成为Singleton会使它的客户端测试十分困难, 因为无法给Singleton替换模拟实现, 除非他实现一个充当其类型的接口 .
在jdk1.5之前.singleton两中方法都要私有化构造器,并导出共有的静态成员 . 以便客户端能够访问该类的唯一实例 .
如:
public class Elvis{
public static final Evlis INSTANCE = new Elvis();
private Elvis(){...}
}
但是可以借助AccessibleObject.setAccessible方法, 通过反射机制调用私有构造器 .
如何抵御攻击 ?
修改构造器,让它在被要求建立第二个实例的时候抛出异常.
在实现singleton 第二方法中, 共有成员是个静态工厂方法 .
对于静态方法Elvis.getInstance的所有调用, 都会返回同一个对象的引用. 所以永远补会创建其他的Elvis实例 .
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis(){
...}
public static Elvis getInstance(){ return INSTANCE ; }
...
}
公共域优势
组成类的成员的生命很清晰的表明了这个类是一个singleton ;
公有的静态域是final的 , 所以该域将总是包含相同的对象引用 .
公有域方法在性能上不在有任何优势.
工厂方法优势
灵活性 在不变api的前提下 , 我们可以改变该类是否该singleton的想法.比如改为每个调用该方法的线程返回一个唯一的实例 .
Singleton 序列化问题
为了使singleton可序列化,仅仅加上 implements Serizlizable 是不够的 , 为了维护并保证Singleton 必须生命所有实例域都是 瞬时 transient 的 ,并提供readResolve方法. 否则反序列化是都会建立一个新的实例 , 比如在例子中会导致”假冒Elvis” ,为防止这情况 , 要在Evlis类中加入下面readResolve方法 .
private Object readResolve(){
return INSTANCE ;
}
JDK1.5 Singleton
jdk1.5开始加入了枚举类型 enum , 只需要编写一个包含单个元素的枚举类型 .
这种方法在功能上与公有域方法相近,但是他更加的简洁,无偿第提供了序列化机制 , 绝对防止多次序列化,即使是爱面对复杂的序列化/反序列化攻击都没有问题 .枚举类方法的singleton是jdk1.5以来最佳的实现方法.
关于详细介绍参考我的另一篇文章 .
http://blog.csdn.net/maguochao_mark/article/details/51423725
public enum Elvis {
INSTANCE ;
}
三 避免建立不必要的对象
一般而言,最好能重用对象而不是在每次使用是建立新的对象. 重用的方式既快捷又方便,如对象是不可变的immutable 那么它始终可以被重用 .
String s = new String("string");
这句就建立了两个String对象 “string”本身就是一个string对象了 , 然后作为参数又传入了String的构造器,又生成了一个新的string对象,如果这个方法在一个循环中 , 或在以个频繁调用的方法中,就会建立出很多不必要的对象.
String s = "string" ;
建立一个实例, 而且它可以保证对于所有在同