在 Java 中创建无状态实用程序类的最佳实践是什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40996614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 05:36:14  来源:igfitidea点击:

Whats the best practice for creating Stateless Utility classes in Java

javadesign-patterns

提问by Yogesh

What's the best practice for creating the Utility (which do not hold any state) classes in Java.

在 Java 中创建实用程序(不包含任何状态)类的最佳实践是什么。

In most of the cases we end up creating static methods for such tasks. Other possible way could be "create the singleton objects" for performing this operation.

在大多数情况下,我们最终会为此类任务创建静态方法。其他可能的方法是“创建单例对象”来执行此操作。

What should be the design consideration when requirement is the code should be easily unit testable?

当要求代码应该易于单元测试时,设计考虑应该是什么?

回答by VGR

If you'll indulge my metaphor for a bit…

如果你稍微放纵一下我的比喻……

You probably have seen one of these before:

您之前可能已经看过其中之一:

Device

设备

Notice that we call it a toaster. We do notcall it a “BreadUtil.”

请注意,我们称其为烤面包机。我们称其为“BreadUtil”。

Similarly, utility methods can and should be placed in a class named for specific functionality, not “miscellaneous stuff related to bread.”

类似地,实用方法可以而且应该放在一个以特定功能命名的类中,而不是“与面包相关的杂项”。

Most of the time, your static methods belong on a related class; for instance, Integer.parseIntis a static method of the Integer class, not a member of a theoretical IntegerUtil or NumberUtil class.

大多数时候,你的静态方法属于一个相关的类;例如,Integer.parseInt是 Integer 类的静态方法,而不是理论上的 IntegerUtil 或 NumberUtil 类的成员。

In the past, one case for creating a separate utility class was when the primary class of interest was an interface. An example of this is java.util.Collections. However, as of Java 8, this is not an excuse, as interfaces can have static methods and default methods. In fact, Collections.sort(List) has already been migrated to List.sort.

过去,创建单独的实用程序类的一种情况是当感兴趣的主要类是接口时。这方面的一个例子是java.util.Collections。但是,从 Java 8 开始,这不是借口,因为接口可以有静态方法和默认方法。实际上, Collections.sort(List) 已经迁移到List.sort

If you have a lot of utility methods and you feel they would clutter the relevant class, it's fine to put them in a separate class, but not a “BreadUtil” class. It is never acceptable to put the word “util” in a class name (or “utils,” “utilities,” “misc,” “miscellaneous,” “general,” “shared,” “common,” or “framework”). Give the class a meaningful name that describes what the methods are for. If the methods are too diverse to allow for such a class name, you probably need to split them up into multiple classes. (Small classes with only a few methods are perfectly acceptable; many people even consider that good design.)

如果您有很多实用方法,并且您觉得它们会使相关类变得混乱,那么将它们放在一个单独的类中是可以的,但不是“BreadUtil”类。将“util”这个词放在类名(或“utils”、“utilities”、“misc”、“miscellaneous”、“general”、“shared”、“common”或“framework”)中是不可接受的. 为类指定一个有意义的名称,以描述这些方法的用途。如果方法过于多样化而不允许使用这样的类名,您可能需要将它们拆分为多个类。(只有少数方法的小类是完全可以接受的;许多人甚至认为这是好的设计。)

Going back to the Integer example, if you felt the methods were cluttering the class, you could create new classes like this:

回到 Integer 示例,如果您觉得这些方法使类变得混乱,您可以像这样创建新类:

public class IntegerMath {
    private IntegerMath() { }

    public static int compare(int x, int y) { /* ... */ }
    public static int compareUnsigned(int x, int y) { /* ... */ }
    public static int divideUnsigned(int dividend, int divisor) { /* ... */ }
    public static int min(int a, int b) { /* ... */ }
    public static int max(int a, int b) { /* ... */ }
    public static int remainderUnsigned(int dividend, int divisor) { /* ... */ }
    public static int signum(int i) { /* ... */ }
    public static int sum(int a, int b) { /* ... */ }
    public static long toUnsignedLong(int i) { /* ... */ }
}

public class IntegerBits {
    private IntegerBits() { }

    public static int bitCount(int i) { /* ... */ }
    public static int highestOneBit(int i) { /* ... */ }
    public static int lowestOneBit(int i) { /* ... */ }
    public static int numberOfLeadingZeros(int i) { /* ... */ }
    public static int numberOfTrailingZeros(int i) { /* ... */ }
    public static int reverse(int i) { /* ... */ }
    public static int reverseBytes(int i) { /* ... */ }
    public static int rotateLeft(int i, int distance) { /* ... */ }
    public static int rotateRight(int i, int distance) { /* ... */ }
}

public class IntegerParser {
    private IntegerParser() { }

    public static int parseInt(String s) { /* ... */ }
    public static int parseInt(String s, int radix) { /* ... */ }
    public static int parseUnsignedInt(String s) { /* ... */ }
    public static int parseUnsignedInt(String s, int radix) { /* ... */ }
}

The last of those is an example of something that might be better without static methods:

最后一个是没有静态方法可能会更好的例子:

public class IntegerParser {
    public IntegerParser() { this(10); }
    public IntegerParser(int radix) { /* ... */ }

    public int parseInt(String s) { /* ... */ }
    public int parseUnsignedInt(String s) { /* ... */ }
}

回答by Adrian Ber

I think the most common way is to create static methods. As an example see StringUtils in Apache Commons Lang, Strings in Guavaor even Arrays in JDK.

我认为最常见的方法是创建静态方法。举个例子看到了Apache Commons Lang中StringUtils的番石榴字符串,甚至在JDK阵列

Also the class should be made final and it should have a private constructor to avoid inheriting it or instantiating it.

此外,该类应该是最终的,并且它应该有一个私有构造函数以避免继承它或实例化它。

Either you use static methods or a singleton, it should be the same effort to unit test it. In the latter case, you might write a little bit more code (characters).

无论您使用静态方法还是单例,都应该对其进行单元测试。在后一种情况下,您可能会编写更多的代码(字符)。

I know that OO purists will argue the very existence of such classes and I will tend to agree with them, but these are added only for the sake of simplicity and you should limit the number of such classes.

我知道 OO 纯粹主义者会争论此类类的存在,我倾向于同意他们的观点,但添加这些只是为了简单起见,您应该限制此类类的数量。

回答by theDima

If you use frameworks like Spring, you can create a utility class with @Serviceannotation. This will ensure it's single instace (SIngleton), and an easy way to inject it itno any other class which'll have a need in its methods.

如果您使用 Spring 等框架,则可以创建带有@Service注解的实用程序类。这将确保它是单一实例(SIngleton),并且是一种简单的方法来注入它,而不是任何其他需要其方法的类。

In any other case, I'd suggest to make it a singleton, using factory pattern, or in cotrast, using only static methods.

在任何其他情况下,我建议使用工厂模式将其设为单例,或者在对比中仅使用静态方法。

回答by René Link

What's the best practice for creating the Utility (which do not hold any state) classes in Java.

在 Java 中创建实用程序(不包含任何状态)类的最佳实践是什么。

In my opinion the best way is to omit utility classes whenever possible.

在我看来,最好的方法是尽可能省略实用程序类。

A utility class reverses the idea of object-oriented programming. When you come to the point that you need a new method you usually add it to the class with the highest cohesion. This means to the class that holds most of the information the method needs. The other information will be passed into the method as parameters. If the parameter list gets too long it is often an indicator for a misplaced method.

实用程序类颠倒了面向对象编程的思想。当您需要一个新方法时,通常会将其添加到具有最高内聚力的类中。这意味着拥有方法所需的大部分信息的类。其他信息将作为参数传递到方法中。如果参数列表太长,则通常表明方法放错了位置。

There are rare situations when you really need a utility class to provide a method for some type. E.g.

在极少数情况下,您确实需要一个实用程序类来为某些类型提供方法。例如

  • if you can't add the method to the source code, because you do not own it (But you might either create a wrapper or subclass it)
  • if a class that needs the additional method is final and you don't own the source code (e.g. StringUtility)
  • 如果您不能将该方法添加到源代码中,因为您不拥有它(但您可以创建一个包装器或子类化它)
  • 如果需要附加方法的类是 final 并且您不拥有源代码(例如 StringUtility)

In most of the cases we end up creating static methods for such tasks. Other possible way could be "create the singleton objects" for performing this operation.

What should be the design consideration when requirement is the code should be easily unit testable?

在大多数情况下,我们最终会为此类任务创建静态方法。其他可能的方法是“创建单例对象”来执行此操作。

当要求代码应该易于单元测试时,设计考虑应该是什么?

If you take a look at utility classes from a unit testability perspective and you want to be able to mock the utiltiy class you should use the singleton, because object references can be replaced.

如果您从单元可测试性的角度查看实用程序类,并且希望能够模拟实用程序类,则应该使用单例,因为可以替换对象引用。

Either by changing the singleton instance reference (the static variable) or at the client side by using an object field. E.g.

通过更改单例实例引用(静态变量)或在客户端使用对象字段。例如

 private SomeUtility someUtility = SomeUtiltiy.INSTANCE;

 public void someMethod(...){
    // Can be replaced by changing the someUtility reference
    someUtility.doSomething(....); 

    // A static call like 
    // SomeUtility.doSomething(...);
    // can not be easily replaced.
 }

Static method calls are hard to replace. Some test frameworks like powermocksupport mocking of static callsby rewriting the client bytecode. But I think that those frameworks were designed to support unit testing of bad legacy code. If you need powermock for new code you should rethink your design.

静态方法调用很难替换。一些测试框架,例如通过重写客户端字节码来powermock支持模拟静态调用。但我认为这些框架旨在支持不良遗留代码的单元测试。如果您需要为新代码使用 powermock,您应该重新考虑您的设计。

回答by Vadim

Static is a singleton. singleton instance with non-static methods need only when you need multiple Utility class variations with different property(ies)/setting(s) value(s) to use. As example when your utility has some property (i.e. customProperty) and you need two different cases at the same time.

静态是单例。仅当您需要使用具有不同属性/设置值的多个实用程序类变体时,才需要使用非静态方法的单例实例。例如,当您的实用程序具有某些属性(即 customProperty)并且您同时需要两种不同的情况时。

  1. when Utility need to use customProperty=value1

  2. when Utitlity need to use customProperty=value2...

  1. 当 Utility 需要使用 customProperty=value1

  2. 当Utility需要使用customProperty=value2...

but it is quite strange, clumsy and not good... Utility caller can provide needed property value into static method. So, do not stuck with that. Make Utility methods always static and do not care about "theoretical" patterns... :)

但它很奇怪,笨拙而且不好......实用程序调用者可以将所需的属性值提供到静态方法中。所以,不要坚持下去。使实用程序方法始终保持静态并且不关心“理论”模式...... :)