Skip to content
Advertisement

Duplicate code across enums .. is there an approach to centralize common code in these enums?

I have the following 3 enum’s in my project, which are all very similar.

Since each enum has at least 2 common fields i.e key and code, is there any way that I can make the common:

  • constructors
  • getters
  • field declarations

shared to all of my enums? Without having to declare inside each one.

I know no extends clause allowed for enum.

But is there an elegant way to achieve reuse of the common parts of these enums?

public enum CarType {

  SEAT("2000", "001"),
  FIAT("3000", "002");

  String key;

  String code;

  CarType(String key, String code) {
    this.key = key;
    this.code = code;
  }

  public String getKey() {
    return key;
  }
  public String getCode() {
    return code;
  }
}

public enum TruckType {

  MERCEDES("4000", "001"),
  FORD("5000", "002");

  String key;

  String code;

  TruckType(String key, String code) {
    this.key = key;
    this.code = code;
  }

  public String getKey() {
    return key;
  }
  public String getCode() {
    return code;
  }
}

public enum VanType {

  JEEP("6000", "001", "40"),
  KIA("7000", "002", "50");

  String key;

  String code;

  String tankSize;

  VanType(String key, String code, String tankSize) {
    this.key = key;
    this.code = code;
    this.tankSize = tankSize;
  }

  public String getKey() {
    return key;
  }
  public String getCode() {
    return code;
  }
  public String getTankSize() {
    return tankSize;
  }
}

Advertisement

Answer

Enum – is a special kind of class that is very restricted. And you may think of enum constants as if they are public static final fields (note: explicit modifiers are not allowed with enum constants).

That actually resembles the Singleton pattern.

All enum constants are eagerly initialized when an enum is being loaded into memory. And that is the simplest implementation of the singleton when an instance (in this case instances) is being initialed before any of its static methods of fields can be accessed.

My idea is to introduce an abstract class VehicleType that will contain two string fields key and code, constructor and getters.

And every enum will turn into a concrete class that extends the VehicleType class. Apart from constructors and static final fields in these classes, we’ll need to declare only a single field inside the VanType and provide a getter for it.

The code for that will look like that.

public abstract class VehicleType {
    protected String key;
    protected String code;

    public VehicleType(String key, String code) {
        this.key = key;
        this.code = code;
    }

    // getters + common behaviour
}
public class CarType extends VehicleType {
    public static final CarType SEAT = new CarType("2000", "001");
    public static final CarType FIAT = new CarType("3000", "002");

    private CarType(String key, String code) {
        super(key, code);
    }
}
public class TruckType extends VehicleType {
    public static final TruckType SEAT = new TruckType("4000", "001");
    public static final TruckType FIAT = new TruckType("5000", "002");

    private TruckType(String key, String code) {
        super(key, code);
    }
}
public class VanType extends VehicleType {
    public static final VanType JEEP = new VanType("6000", "001", "40");
    public static final VanType KIA = new VanType("7000", "002", "50");

    private String tankSize;

    private VanType(String key, String code, String tankSize) {
        super(key, code);
        this.tankSize = tankSize;
    }

    public String getTankSize() {
        return tankSize;
    }
}
Advertisement