使用私有构造函数强化singleton属性

singleton是指这样的类,它只能实例化一次。singleton通常被用来代表那些本质上具有唯一性的系统组件,比如视频显示或者文件系统。

实现singleton有两种方法。这两种方法都要把构造函数保持为私有的,并且提供一个静态成员,以便允许客户能够访问该类唯一的实例:在第一种方法中,公有静态成员是一个final域:

//Singleton with final field
public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    
    private Elvis() {
      ...
    }

    ...  // Remainder omitted
}

私有构造函数仅被调用一次,用来实例化公有的静态final域Elvis.INSTANCE,由于缺少公有的或者受保护的构造函数Elvis,所以保证了Elvis的全局唯一性:一旦Elvis类被实例化之后,只有一个Elvis实例存在----不多也不少。客户的任何行为都不会改变这一点。

第二种方法提供了一个公有的静态工厂方法,而不是公有的静态final域:

public class Elvis {

    private staitc final Elvis INSTANCE = new Elvis();

    private Elvis() {
       ...
    }

    public static Elvis getInstance() {
       return INSTANCE;
    }

    ....  //Remainder omitted

}

所有对于静态方法Elvis.getInstance的调用,都会返回同一个对象引用,所以,不会有别的Elvis实例被创建。

第一种方法的主要好处在于,组成类的成员的声明很清楚地表明了这个类是一个singleton:公有的静态域是final的,所以该域总是包含相同的对象引用。第一种方法可能在性能上稍微领先,但是在第二种方法中,一个优秀的JVM实现应该能够通过将静态工厂方法的调用内联化,来消除这种差别。

第二种方法的主要好处在于,它提供了灵活性:在不改变API的前提下,允许我们改变想法,把该类做成singleton,或者不做成singleton,singleton的静态工厂方法返回该类的唯一实例,但是它也很容易被修改,比如说,为每个调用该方法的线程返回一个唯一的实例。

总而言之,如果你确信该类将永远是一个singleton,那么使用第一种方法是有意义的。如果希望保留一点余地,那么请使用第二种方法。

为了使一个singleton类变成可序列化的(serializable),仅仅在声明中加上“implements  Serializable”是不够的,为了维护singleton性,你必须也要提供一个readResolve方法:

private Object readResolve() throws ObjectStreamException {
  /**
   * Return the one true Elvis and let the grabage collector
   * take care of the Elvis impersonator
   *
  return INSTANCE;
}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值