【问题标题】:Private constructor in singleton单例中的私有构造函数
【发布时间】:2017-01-10 20:24:04
【问题描述】:
 public class DBSingleton {

 private static DBSingleton instance = new DBSingleton();

 private DBSingleton() {
 // why do we need this constructor
 }
 public static DBSingleton getInstance() {
     return instance;
 }
}

私有构造函数如何帮助我?

我的意思是所有变量和方法都是静态的,即使我将构造函数公开,它也不会改变任何东西。
假设有人创建了我的单例对象,什么都不会发生,因为此类中的所有内容都是静态的,这意味着与类本身相关联,而不是与对象相关联。 Java 静态属性被所有对象共享。

谁能给我一个合理的例子

【问题讨论】:

  • 首先,单例不一定必须作为具有静态方法的类来实现。其次,当对象创建本身很繁重(CPU/网络/等)时,您希望控制创建的实例数量,例如连接池。
  • 因为如果你的构造函数是公共的,任何人都可以调用它,从而创建你的单例的其他实例,这违背了单例的全部目的。如果创建多个实例不成问题,那为什么首先要让它成为单例呢?如果一切都是静态的,为什么还要创建一个实例?
  • 这甚至不是一个单例。如果不创建DBSingleton 的实例,就无法访​​问instance,而由于构造函数是私有的,因此无法完成。你的意思可能是public static DBSingleton getInstance()
  • @alfasin 感谢您的链接,但我没有找到问题的答案,这是完全不同的
  • 正如我在另一条评论中所说,如果所有字段和方法都是静态的,那么创建单例就毫无意义。您根本不需要任何实例来访问类的静态成员。所以让它成为一个单例会让人很困惑,并且表现出缺乏理解。将构造函数设为私有,并且不提供任何 getInstance() 方法,这清楚地表明您永远不应该实例化该类。

标签: java design-patterns singleton


【解决方案1】:

您需要一个私有构造函数来防止用户实例化您的类。

如果你公开你的构造函数,用户可以做DBSingleton singleton = new DBSingleton(),你的类就不是单例了!

【讨论】:

  • 是的,但不会有太大变化,因为 java 的静态属性是共享给所有对象的。所有字段都被声明为静态,因此即使用户做了 DBSingleton singleton = new DBSingleton() 他也将访问相同的字段。我说的对吗?
  • @M.T 没有。如果所有字段和方法都是静态的,那么创建单例就毫无意义。您根本不需要任何实例来访问类的静态成员。所以让它成为一个单例会让人很困惑,并且表现出缺乏理解。将构造函数设为私有,并且不提供任何 getInstance() 方法,这清楚地表明您永远不应该实例化该类。
  • “所有字段都被声明为静态” 这不是 Java 的做法。由于 Java 是一种 OO 语言,因此您应该使用对象来通过接口从多态性和抽象中受益。如果您认为这是“矫枉过正”,那么您为什么要使用 Java?那里有很多非 OO 语言...
  • @JBNizet 我不太明白你的意思,我提供了 getInstance 方法。 java中是否有其他不使用静态字段的单例设计模式实现?
  • 单例的全部意义在于拥有一个唯一的instance类,具有instance字段和instance方法。这样您就可以将此实例作为参数传递,实现接口等。如果所有方法都是静态的,那么拥有一个实例是完全没用的:您将它用于什么?
【解决方案2】:

单例类(编辑:与单例实例比较 - 参见 cmets)甚至不需要实例化;给它一个私有构造函数并将所有其他方法声明为静态就足够了,从而强制用户在类上调用它们。

构造函数必须是私有的,以确保类是单例,无论您是否创建它的单个实例。如果没有声明私有构造函数,Java 会自动为其提供一个公共的无参数构造函数。

为了安全起见,该类需要是单个实例,也就是说,如果您想在其上调用完全按照单例所说的方法执行的方法。如果您有一个未明确设为单例的类的实例,那么当您在其上调用方法时无法保证它正在运行单例的实现,因为您实际上可能有一个 DBSingleton 的子类,其中所说的方法被覆盖。 (如果您将它们调用为DBSingleton.someMethod(),您当然会得到预期的行为,但如果您这样做:

DBSingleton dbsInstance = DBSingleton.getInstance();
// ... all sorts of code, some of which might affect dbsInstance
dbsInstance.someMethod();

所有赌注都取消了。)

声明一个类以避免其他实例的更正确方法是将其声明为final。你给它一个私有构造函数,这样它也不能被实例化。 (最终类或具有私有构造函数的类(或者更确切地说,零个非私有构造函数)足以使该类不可覆盖。)

【讨论】:

  • 拥有一个可能实例为零且只有静态方法的类很好,但绝对不是单例。
  • @JBNizet 它是一个单例,因为用户只能使用类(作为实例)并且不能创建同一个类的多个实例。
  • 好吧,不,他们不能像使用类的实例一样使用类:如果只有静态方法,就无法实现接口。没有办法扩展抽象类。没有办法将实例存储在集合中等等等等。无论如何,单例有一个精确的含义,它与“实用程序类”不同?用一个词来形容另一个词只会造成混乱。
  • 我同意 JB Nizet 的观点,但我认为他有点在与历史作斗争——他所谓的“实用类”在很多其他地方都被称为“单身”,而且他是对,这令人困惑。而且我更倾向于看到(错误标记的)实用程序类,而不是真正的单例,这使情况变得更糟。我自己对此有点懈怠。但这可能不会很快消失。
  • @JBNizet 这个讨论让我更加困惑)
猜你喜欢
  • 2013-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
相关资源
最近更新 更多