我遇到的一件事是服务类(比如JBoss服务)由于帮助器内部类而变得过大。我还没有找到一个打破课堂的好方法。这些助手通常是线程。这是一个例子:
/** Asset service keeps track of the metadata about assets that live on other
* systems. Complications include the fact the assets have a lifecycle and their
* physical representation lives on other systems that have to be polled to find
* out if the Asset is still there. */
public class AssetService
{
//...various private variables
//...various methods
public AssetService()
{
Job pollerJob = jobService.schedule( new AssetPoller() );
Job lifeCycleJob = jobService.schedule( AssetLifecycleMonitor() );
}
class AssetPoller
{
public void run()
{
// contact remote systems and update this service's private variables that
// track the assets.
}
}
class AssetLifecycleMonitor
{
public void run()
{
// look for assets that have meet criteria for a lifecycle shift
// and update this service's private variables as relevant.
}
}
}
所以,如果我有几个帮助器并且它们都很复杂会发生什么,整个类文件会变得非常大。我喜欢内部类,因为它清楚地表明类是由服务完全拥有的,并且仅存在于帮助该服务。我已经尝试打破这些类并将父服务作为参考传递,这主要起作用,但我不喜欢的是:
因此,简而言之,打破课程会失去一些我喜欢的封装。但是留下它们会导致一些大的java文件。我还没有找到解决这个问题的好方法。 C ++有“朋友”的概念,我很少会错过,但在这种情况下实际上会有所帮助。
思想?
答案 0 :(得分:7)
在字节码级别,内部类只是普通的Java类。由于Java字节码验证程序不允许访问私有成员,因此它为您使用的每个私有字段生成合成访问器方法。此外,为了将内部类与其封闭实例链接,编译器将合成指针添加到外部“this”。
考虑到这一点,内部类只是一层语法糖。它们很方便,你列出了一些优点,所以我列出了一些你可能想要考虑的消极方面:
P.S。我在谈论非平凡的内部类(特别是那些没有实现任何接口的内部类)。三线侦听器的实现很好。
答案 1 :(得分:3)
封装和分离之间的界限很难走。但是,我认为这里的主要问题是你需要某种可靠的交互模型作为分离你的类的基础。
我认为在许多地方使用外部帮助程序实用程序类是合理的,只要它们没有副作用我没有看到问题。拥有静态帮助程序类也是合理的,只要它们组织良好,它们包含常用的方法,如checkAssetIsValid()。这假设checkAssetIsValid不需要访问除传递它的对象之外的任何外部状态。
分离最重要的事情不是拥有在许多这些类中共享永久引用的对象。我喜欢看功能性编程以获得指导。每个班级都不应该达到其他班级的内涵和改变状态。相反,每个工作的类都应该生成和使用容器对象。
可视化也非常有用。我注意到了关于Java Visualization工具here主题的一个主题。理想情况下,您的类交互图应该看起来更像树而不是图形。
另外,我只想指出将大型类重构为较小的类可能非常困难。最好至少为公共接口构建一套单元测试,以便在你破坏某些东西时立即变得明显。我知道过去的测试为我节省了无数个小时。
希望其中一些会有所帮助。我只是在这里闲聊。
答案 2 :(得分:3)
不要忘记考虑为什么要分手你的大班。它是出于软件工程目的吗?例如。它是一个编程热点,你有这么大的文件导致开发团队的复杂合并?
这只是避免大班的一般愿望吗?在这种情况下,您可能会花更多时间来改进您所拥有的代码。
代码是否难以管理,例如调试和确保避免意外的副作用变得越来越困难。
Rick关于使用单元测试来确保持续一致行为的评论是非常有价值的,也是一个好主意。可能是当前的设计只是简化了重构,你最好从原始界面开始重新实现相同的行为。准备进行大量的回归测试!
答案 3 :(得分:1)
我不喜欢过度使用内部类。我认为它们并没有真正提供任何优势(在极端情况下使用时)将代码放在普通类中不会,并且它们只是用于使类文件不必要地大而且难以遵循。
如果必须提高几种方法的可见性,会有什么危害?是否会彻底打破你的抽象或界面?我认为程序员往往会默认将所有内容设为私有,其中一些其他类调用您的方法并没有太大的危害 - 如果您的设计真的是基于OO的,那就是。
如果所有“内部帮助器类”都需要访问某些相同的方法,请考虑将它们放在基类中,以便可以通过继承来共享它们。
答案 4 :(得分:0)
叶氏。可能你需要重新重构那些帮助者而不是按原样移动它们。有些东西属于帮助者的其他服务。应该使用可能的新类来封装数据。
您可以使用的一个可能性是AOP提供细粒度访问,并且在切入点中包含该方法应仅从“朋友”类调用。仍然会暴露你的方法:(
我想这没有简单的解决办法。