简体   繁体   中英

Java, interface or composition for constants class

I have a question regarding the design of my program. I have a class A that stores public constant so that i can use these constants in another class.

public static final String error_code1 = "Fatal Error";
public static final String error_code2 = "XXXX";
...
...

Between Composition vs Interface, i dont know which 1 is more suitable. From what i think, since i only need the constants for value-comparing in my program, so i think composition is enough (low coupling).

But can you guys give me some advice/arguments from software deign point of view? (cohesion, coupling, difficulties of maintenance, etc )

First of all I'd recommend you to use an enum for this case.

public enum ErrorCode {
    FATAL_ERROR("Fatal Error"),
    X_ERROR("XXXX");

    public final String msg;
    private ErrorCode(String msg) {
        this.msg = msg;
    }
}

If this doesn't suit you for some reason, I'd go with a final utility class with private (unused) constructor.

Regardless, since the fields are static and final, I would not consider having a reference to A or implement A to get hold of the constants.

Adding constants to interfaces is considered an anti-pattern since the primary purpose of an interface is to define behavior contracts. Use either an enum or access them directly since they are public.

I wouldn't use interface to store constant as having static members into an interface (and implementing that interface) is a bad practice and there is even a name for it, the Constant Interface Antipattern , see [Effective Java][1], Item 17:

The constant interface pattern is a poor use of interfaces . That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.

I would personally go for enum and if needed i could even use it to have error code or add relevant field/method as well.

String/int/... constants in another class have one problem: they are copied into the using class' constant pool, and after that no import to the original class exists. Should you then alter a constant's value, the using class is not forced to be recompiled.

The solution would be to use an interface, and "implement" that interface; ugly maybe. Better is to use an enum.

For open ended value domains one would not use an enumeration, but an object oriented approach:

abstract class ParseError extends RuntimeException
class ExpressionExpectedError extends ParseError
class DigitsMayNotFollowLeadingZeroError extends ParseError
..

In the javadoc one might see all child classes of ParseError. Here the classes themselves form the domain values, and an instantiation bears the actual context information. That is more OOP. Calling several methods on an object is better than having several switches on constants. An enum however may be used with categorical method too: boolean errorHandledBySkippingToNextExpr() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM