【问题标题】:Only one class can instantiate all other clases只有一个类可以实例化所有其他类
【发布时间】:2019-09-24 21:53:57
【问题描述】:

将类的实例化限制为仅一个类的最佳做法是什么?类似于 this 的东西,但在 Java 中。

假设有 Main 类,然后有 User、Admin、View、Data、Client 等类。只有“主”类应该能够实例化所有其他类。

所以如果'User'需要在'Data'类中调用'getUser'方法,它不能实例化'Data'类和调用方法,但它必须调用'Main'类,然后'Main'会实例化“Data”类并将参数传递给它的“getUser”方法。

我在想的是使用私有构造函数、工厂模式等,但不确定这是否会产生我需要的结果。由于复杂性,我认为内部类不是一个好的解决方案。

对此有何建议?

【问题讨论】:

  • 你想要保证类永远不会被除 Main 之外的类实例化,还是这更像是一种不污染命名空间的实践?如果是第二种,您可以将 Main 包以外的类的构造函数设为私有,并确保它们都在自己的包中?
  • 这就是 Java 包的用途。您可以将事情设为包私有(当您不说公开时,这实际上是默认设置),然后其他包中的代码无法访问它。这样,您可以将构造函数(甚至整个类)隐藏在用户代码中,并保留在您自己的实现内部。
  • 我看不出想要这样做的充分理由。这似乎是一种很好的方法,可以实现很多复杂性,但没有太多好处(而且可能有相当多的损害)。
  • @adickinson 是的,我想保证这些类永远不会被 Main 以外的类实例化。是的,我可以使类的构造函数是私有的,并且所有类都在单独的包中。
  • 保护所有构造函数,并提供一个工厂公共方法

标签: java


【解决方案1】:

概念层面的独特答案(因为在技术“如何做”方面已经有了很好的答案):

假设有 Main 类,然后有 User、Admin、View、Data、Client 等类。只有 'Main' 类应该能够实例化所有其他类。

我认为这不是一个好的起点。当然,当遵循领域驱动设计时,使用factories 已经很成熟了。

但有一点需要补充:您仍然希望以合理的方式削减您的“界限”。含义:不要强制所有对象进入一个单个工厂。您的对象应该在某种程度上类似于它们的域,并在需要的地方分开。

含义:使用工厂很好,但不要强迫自己进入错误的角落,强制要求确实有一个工厂应该处理各种你处理的对象。相反:尝试合理地划分您的对象模型,并拥有尽可能多的工厂,因为它在概念上是有意义的。

还请注意,您可能应该区分主要提供数据/信息的对象和最后的“行为”。因此,可能值得考虑使用 服务注册表 的想法(例如,您使用 netflix Eureka 框架所做的事情,请参阅 here)。

最后,在这里引用tucuxi 给出的出色评论:对于小型应用程序,工厂过度设计。对于更大的应用程序,我发现有一个名为“Main”的工厂是有问题的,而不是以更正统的方式划分职责。

【讨论】:

  • 这是(目前)唯一解决“最佳实践”问题是否实际上是指“良好实践”的问题的答案。对于小型应用,工厂过度设计。对于更大的应用程序,我发现有一个名为“Main”的工厂是有问题的,而不是以更正统的方式划分职责。
  • @tucuxi 我喜欢你的评论。以至于我将它添加到我的答案中;-)(将在其他地方表达我的感激之情)
【解决方案2】:

您可以使用带有私有构造函数的子类: 这样,只有 InstantiatonClass 可以创建 InstantiatonClass.ArgClass 和 ProtectedClass 的构造函数。

public class ProtectedClass{
    //constructor that can only be invoked with an instance of ArgClass 
    public ProtectedClass(InstantiatonClass.ArgClass checkArg){}
}
public class InstantiatonClass{
    public static class ArgClass{
    //constructor that can only be invoked from InstantiatonClass
        private ArgClass(){}
    }
}

【讨论】:

  • 不符合要求。
【解决方案3】:

您应该能够在 Class 的构造函数中获取调用者的类:

How to get the name of the calling class in Java?

然后在你只想被 Main 实例化的类中,只需在其构造函数中检查调用者类是否为 Main,如果不抛出 RuntimeException。

【讨论】:

    猜你喜欢
    • 2010-12-28
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    相关资源
    最近更新 更多