正确实现按需初始化持有者习语 [英] Correct implementation of initialization-on-demand holder idiom

查看:141
本文介绍了正确实现按需初始化持有者习语的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个版本的按需持续保持成语:


  1. http://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom

  2. http://en.wikipedia.org/wiki/Singleton_pattern#The_solution_of_Bill_Pugh

上面的主要区别是第一个声明 INSTANCE private ,但第二个已将 INSTANCE 声明为公开



请告诉我应该使用哪个。 / p>




对不起,我没有发现使用私人 strong>在我的应用程序:

  public class Singleton {
private int x;
public int getX(){
return x;
}

private Singleton(){}

私人静态类LazyHolder {
//私人和公共作品
私人静态Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance(){
return LazyHolder.INSTANCE;
}
}

我所做的只是调用 Singleton.getInsance()。getX(),所以这两个版本都工作。
因此我想知道使用它们的情况。

解决方案

有几个事情要解释单例和按需初始化持有者习语。我们去:



1)访问修饰符:



通常你不能访问字段和方法如果他们是私人的另一个类。如果访问类在同一个包中,它们必须至少是包私有(没有修饰符)。所以正确的实现方法是:

  public class Singleton {
...
private static class LazyHolder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return LazyHolder.INSTANCE;
}
}

但是, JLS 6.6.1 说明:


否则,如果成员或构造函数被声明为私有的,则访问是
,如果且仅当它出现在顶级类的主体中时才允许


这意味着,声明字段 INSTANCE

code> as private仍允许从顶层类 Singleton 内部访问。但是编译器必须做一些技巧来解决private修饰符:它插入包私有方法来获取和设置这样的字段。



事实上,没关系,你放在它上面的修饰符。如果它是public,它仍然不能从 Singleton 的其他类访问。但是...我认为包私人访问是最好的。使它公开没有意义。使它私有强制编译器做一些技巧。使它的包私有反映你有:从另一个类访问类成员。



2)如何实现单例:



如果你想考虑序列化,单例实现会有点困难。 Joshu Bloch在他的Effective Java一书中写了一个关于实现单例的很好的部分。最后,他总结说,为了简单地使用枚举,因为Java枚举规范提供了关于单例需要的每个charecteristic。当然,这不再使用成语。



3)考虑设计:



,单身人士不再有他们的地方。事实上,它可能表明一个设计问题,如果你必须在你的程序中放置一个单例。请注意:单身人士为某些数据或服务提供了全局访问机制。这不是OOP。


I have got two versions of "Initialization-on-demand holder idiom":

  1. http://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
  2. http://en.wikipedia.org/wiki/Singleton_pattern#The_solution_of_Bill_Pugh

The major difference between above is that the first one declared INSTANCE as private, but the second one declared INSTANCE as public.

Please tell me which one should I use.


Sorry, I have not found the difference between using private and public in my application:

public class Singleton {
    private int x;
    public int getX() {
        return x;
    }

    private Singleton () {}

    private static class LazyHolder {
        //both private and public works
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}

The only thing I do is to call something like Singleton.getInsance().getX(), so both versions works. Thus I want to know the situations for using them.

解决方案

There are several things to explain about singletons and the initialization-on-demand holder idiom. Here we go:

1) The access modifier:

Normally you can't access fields and methods in another class if they are private. They must at least be package private (having no modifier, it is) if the accessing class is in the same package. So the correct way to implement it, would be:

public class Singleton {
    ...
    private static class LazyHolder {
        static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}

However, JLS 6.6.1 explains:

Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

That means, declaring the field INSTANCE as private still allows the access from inside the top level class Singleton. But the compiler must do some tricks to get around the private modifier: It inserts package private methods for getting and setting such a field.

In fact, it does not matter, which modifier you place on it. If it is public, it still cannot be accessed from other classes than Singleton. However ... I think the package private access is the best. Making it public does not makes sense. Making it private forces the compiler to do some tricks. Making it package private reflects what you have: Access to a class member from another class.

2) How to implement a singleton:

If you ever want to consider serialization, the singleton implementation will get a bit difficult. Joshu Bloch wrote a great section in his book "Effective Java" about implementing singletons. At the end, he concluded to simply use an enum for this, as the Java enum specification provides every charecteristic that is needed in regards to singletons. Of course, that does not use the idiom anymore.

3) Considering design:

In most design decisions, singletons do not have their places anymore. In fact, it could indicate a design issue, if you must place a singleton into your program. Keep in mind: Singletons provide a global acess mechanism to some data or services. And this is not OOP.

这篇关于正确实现按需初始化持有者习语的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆