我有一个应用程序,其中有一个名为PlausibilityChecker
的类。这个类只有静态方法,比如checkZipcodeFormat
或checkMailFormat
。我在GUI类中使用它们来在将输入发送到下一层之前检查输入。
这是一种好的做法吗?我认为仅使用静态方法可以使我不必担心向GUI类传递实例或在每个GUI类中具有不引用GUI对象的实例字段。
我注意到Java NIO
的Files
类只有静态方法,所以我认为这不可能是那么糟糕的。
我认为你的做法是正确的。此外,以下是一些关于你的实用类的建议:
static final
。同时,确保这个字段也是不可变的,例如String
。final
,这样其他程序员就无法扩展它。private
,这样其他类就不能创建你的实用类的实例(使用反射或类似方法可能会成功,但没有必要对类进行过度保护)。为什么你不应该这样做?嗯,这是一种奇怪的情况,即你想/需要通过接口注入实用类的实例,而不是直接在你的类中使用它。这篇文章提供了一个例子。这种设计确实很奇怪,但可能会发生(如上面链接所示),但如果你不会遇到这种情况,最好的建议是将构造函数设置为private
。有很多库提供实用类,以帮助我们程序员完成工作。其中最著名的之一是Apache Common库集。它是开源的,你可以查看代码以了解如何设计这些实用类来创建自己的实用类。(免责声明:我不工作或支持这些库,我是它们的快乐用户)
重要提示:避免使用单例模式来创建实用类。
getInstance()
,这样不是更好吗? - Bugs Happen在Java 8中,你现在可以将静态工具类改为带有静态实现的接口。这消除了使类成为final并提供私有构造函数的必要性。只需将“class”更改为“interface”,如果有的话,则删除“final”单词(所有接口都是抽象的,因此它们不能是最终的)。由于接口方法始终是公共的,因此您可以从它们中删除任何公共作用域。如果有私有构造函数,那么也要将其删除(无法使用构造函数编译接口,因为它们无法实例化)。代码量更少,看起来更加简洁。不需要重构已经使用它的任何类。
java.beans.Beans
java.beans.PropertyEditorManager
java.lang.invoke.LambdaMetafactory
java.lang.reflect.Modifier
java.net.URLDecoder ...but not URLEncoder:)
javax.management.DefaultLoaderRepository
javax.management.Query
javax.management.loading.DefaultLoaderRepository
javax.management.relation.RoleStatus
javax.print.ServiceUI
javax.swing.UIManager
javax.swing.plaf.basic.BasicBorders
javax.swing.plaf.basic.BasicGraphicsUtils
javax.swing.plaf.basic.BasicHTML
javax.swing.plaf.basic.BasicIconFactory
javax.swing.plaf.metal.MetalBorders
javax.swing.plaf.metal.MetalIconFactory
javax.swing.text.Utilities
javax.swing.text.html.HTML
在Java中,只有静态方法的类是实用方法的常见模式。标准库中的示例包括Files、Collections和Executors。
对于这种实用程序类,最好确保您的类不能被实例化,以清楚地表明类的意图。您可以通过显式声明私有构造函数来实现这一点。请参阅Josh Bloch的《Effective Java》中的第4条:使用私有构造函数强制执行不可实例化了解详细信息。
如果你只是提供“工具”方法给其他类使用,这是很好的做法。
单例模式在特定情况下是可行的。
为了测试目的,您可能希望模拟对单例的引用,以避免在单元测试期间产生副作用。在这种情况下,使用依赖注入框架(如Spring)处理实例的创建并使用常规方法而不是静态方法,这些方法可以被覆盖,可能是有意义的。
如果仍计划使用静态方法,请确保在多线程环境中使用时调用是线程安全的。(例如双重检查锁定)。
private constructor()
可以防止实例化。 - deathangel908