为什么在Singleton类中使用私有Constructor是强制性的

时间:2012-04-01 10:26:06

标签: java design-patterns

这是我获取数据库连接的单例类。

我在这里有一个问题:为什么必须在单例类中包含一个私有构造函数(在整个应用程序中我只调用一次这个类)并且可以使用静态方法实现类的一个实例?

可以避免这个私有构造函数,还是它是mantadatory?

 public class ConnPoolFactory {
        private static DataSource dataSource;
        private static Connection connection;

        private ConnPoolFactory() {
            System.out.println(" ConnPoolFactory cons is called ");
        }

        public static synchronized Connection getConnection() throws SQLException {

            try {

                if (connection == null) {
                    Context initContext = new InitialContext();
                    Context envContext = (Context) initContext
                            .lookup("java:/comp/env");
                    dataSource = (DataSource) envContext.lookup("jdbc/Naresh");
                    connection = dataSource.getConnection();
                } else {
                    return connection;
                }

            } catch (NamingException e) {
                e.printStackTrace();
            }

            return connection;

        }
    }

10 个答案:

答案 0 :(得分:16)

否则每个人都可以创建一个类的实例,因此它不再是单例。对于单身人员,根据定义,只能存在一个实例。

答案 1 :(得分:6)

Singleton模式通常包含非公共构造函数,原因有两个。必须存在构造函数,因为如果根本没有构造函数,则包含公共默认构造函数。但是,如果你有一个公共构造函数,那么人们可以随意制作自己的单身人士(有人不可避免地会这样做,这意味着可以有不止一个)。

但是,它不一定是私人的。事实上,正如我所听到的那样,GoF指定的Singleton模式提到了 protected 构造函数,原因有些奇怪。关于继承的一些事情,我听说,但单身人士和继承人无论如何都不能很好地融合在一起。

甚至可以拥有一个公共构造函数,只要它可以检测实例是否已存在并抛出异常或其他内容。这足以保证单一性。但这种情况并不常见,因为通过提供两种明显的方法来获取实例,这样做会使事情变得复杂 - 其中只有一种实际可行。如果您不希望外部代码能够创建第二个实例,为什么构造函数应该成为公共接口的一部分?

答案 2 :(得分:6)

如果你不需要延迟启动:

public class Singleton {
    private static final Singleton instance = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() { }

    public static Singleton getInstance() {
            return instance;
    }
}

是最好的方法,因为它是线程安全的。

答案 3 :(得分:5)

如果没有这样的私有构造函数,Java将为您提供默认的公共构造函数。然后,您可以多次调用此构造函数来创建多个实例。那就不再是单身人士了。

答案 4 :(得分:4)

对于singleton pattern,您使用私有构造函数来确保不能创建其他实例,否则它不会是单例。

答案 5 :(得分:3)

静态类与单例不同之处在于单例类强制始终最多只有一个实例。静态类没有实例,只是一组静态函数和静态数据。

因此,对于Singleton类,即一个最多只有一个实例的类,则需要私有构造函数。

在您的示例中,由于连接和dataSource成员,看起来Singleton类比静态类更合适。将这些成员设为私有,将构造函数设为私有,并提供引用静态ConnPoolFactory实例的静态方法。如果instance为null,则创建一个新的,否则只使用它。

答案 6 :(得分:3)

对于单例和实用类,您可以使用enum这是一个最终类,并隐式定义私有构造函数。

enum Singleton {
     INSTANCE
}

enum Utility {;

}

在上面的示例中,您有一个实用程序类,因为您没有实例字段,方法,也没有创建实例。

答案 7 :(得分:2)

你说的评论如果我是我的应用程序的完全拥有者,我将永远不会犯错误直接使用公共构造函数创建单例类的实例,但将使用静态方法来获取它。但在现实世界中,应用程序经常在多个开发人员之间切换。如果新开发人员不知道您只想在应用程序中使用该类的一个实例,则他/她可能会意外地使用公共构造函数创建另一个实例。

答案 8 :(得分:1)

这是强制性的。您的代码可能没问题,但是其他人可以使用此代码并实例化另一个对象,或者您可能会意外地执行此操作。这种方式很安全。

答案 9 :(得分:1)

单身清晰度:

  

确保仅需要为整个主堆栈创建一个对象(每个主类)。

如果您想满足上述声明,那么我们应该将构造函数作为私有变量。实际上,通过单例,我们得到了ref not object,这就是为什么它不是强制性的,然后我们可以在其他类中创建对象,但是我们不能访问引用(构造函数为public)。

例如:

public class SingleTon {

    private static SingleTon s;
    public SingleTon() {}

    public static SingleTon getInstance() {
        if (s == null) {
            s = new SingleTon();
            System.out.println("ho ho");
        } else{
            return s;
        }
        return s;
    }
}

其他班级:

public class Demo {

    public static void main(String[] args) {
        //SingleTon s=SingleTon.getInstance();

        SingleTon s11=new SingleTon();
        SingleTon s12=new SingleTon();
        s11.getInstance();
        s12.getInstance();
    }
}

输出:

ho ho