Whats the best practice for creating Stateless Utility classes in Java [closed]

痴心易碎 提交于 2020-12-28 14:58:01

问题


What's the best practice for creating the Utility (which do not hold any state) classes in 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?


回答1:


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 not call it a “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.parseInt is a static method of the Integer class, not a member of a theoretical IntegerUtil or NumberUtil class.

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.

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.)

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

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) { /* ... */ }
}



回答2:


I think the most common way is to create static methods. As an example see StringUtils in Apache Commons Lang, Strings in Guava or even Arrays in 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.




回答3:


If you use frameworks like Spring, you can create a utility class with @Service annotation. 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.

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




回答4:


What's the best practice for creating the Utility (which do not hold any state) classes in 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)

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 powermock support mocking of static calls by 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.




回答5:


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.

  1. when Utility need to use customProperty=value1

  2. when Utitlity need to use 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... :)



来源:https://stackoverflow.com/questions/40996614/whats-the-best-practice-for-creating-stateless-utility-classes-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!