继承公共接口的枚举中的代码重复

abk*_*srv 7 java enums design-patterns

我有几个符合常见界面的枚举:

    interface TableColumns
    {
      String getColumnName();
      int getColumnIndex();
      ColumnType getColumnType();
      boolean isEditable();
      int getColumnWidth();
    }
Run Code Online (Sandbox Code Playgroud)

典型的实现是:

enum PointsTableColumns implements TrendTableColumns
{
    POINTS_COLUMN("points_column", false, ColumnType.TEXT, 400, 0);

    private String columnName;
    private boolean editable;
    private ColumnType columnType;
    private int columnWidth;
    private int columnIndex;

    private PointsTableColumns (String columnName, boolean editable, ColumnType columnType,
        int columnWidth,
        int columnIndex)
    {
        this.columnName = columnName;
        this.editable = editable;
        this.columnType = columnType;
        this.columnWidth = columnWidth;
        this.columnIndex = columnIndex;
    }

    public boolean isEditable()
    {
        return editable;
    }

    public int getColumnIndex()
    {
        return columnIndex;
    }

    public String getColumnName()
    {
        return columnName;
    }

    public int getColumnWidth()
    {
        return columnWidth;
    }

    public ColumnType getcolumnType()
    {
        return columnType;
    }
}
Run Code Online (Sandbox Code Playgroud)

我有几个这样的实现(10+),每个都有多个几乎不同的值.现在,问题是我在这里看到了很多代码重复,因为所有实现中的方法都是逐字相同的.我知道在Java中这几乎是不可能的,因为枚举不能扩展实现.我需要的是一个建议或不同的策略,可以更清洁地完成.是否已有一些关于此的现有模式?

Fed*_*ner 4

如果您可以接受一级间接,那么我下面介绍的方法会将重复代码减少到最低限度。

首先,考虑以下供应商接口及其内部类:

public interface PropertiesSupplier {

    Properties properties();

    public static final class Properties {

        private final int value1;

        private final String value2;

        private final double value3;

        private Properties(int value1, String value2, double value3) {
            this.value1 = value1;
            this.value2 = value2;
            this.value3 = value3;
        }

        public static Properties of(int value1, String value2, double value3) {
            return new Properties(value1, value2, value3);
        }

        public int getValue1() {
            return this.value1;
        }

        public String getValue2() {
            return this.value2;
        }

        public double getValue3() {
            return this.value3;
        }

        @Override
        public String toString() {
            return "Properties [value1=" + this.value1 + ", value2=" + this.value2 + ", value3=" + this.value3
                    + "]";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这里没什么神奇的。内部类只是一个带有private final字段的 bean、一个用于初始化它们的私有构造函数、公共 getter、一个工厂方法和一个重写toString()方法。该接口仅定义一种返回内部类实例的方法。请注意,内部类是最终的。这个想法是强制不变性,这样它的属性就不允许改变。

然后,让我们创建几个将实现此接口的枚举。让我们从 开始MyEnum1,它定义了两个值:

public enum MyEnum1 implements PropertiesSupplier {
    ENUM_1_CONST_1(Properties.of(1, "hello", 0.123)), 
    ENUM_1_CONST_2(Properties.of(2, "goodbye", 7.54));

    private final Properties p;

    private MyEnum1(Properties p) {
        this.p = p;
    }

    @Override
    public Properties properties() {
        return this.p;
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来是MyEnum2,它只定义一个值:

public enum MyEnum2 implements PropertiesSupplier {
    ENUM_2_CONST_1(Properties.of(9, "hey dude", 547.21578));

    private final Properties p;

    private MyEnum2(Properties p) {
        this.p = p;
    }

    @Override
    public Properties properties() {
        return this.p;
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,两个枚举都实现了该PropertiesSupplier接口,因此它们必须提供该方法的实现Properties properties()。为了遵守这一点,他们必须封装一个 的实例Properties,并在构造函数中接收该实例。

因此,现在,在这种间接寻址之后,在所有枚举中重复的唯一代码就是字段Properties、接收它作为参数的构造函数及其 getter 方法。

这是一个显示如何使用枚举的示例:

MyEnum1 e1 = MyEnum1.ENUM_1_CONST_2;
MyEnum2 e2 = MyEnum2.ENUM_2_CONST_1;

System.out.println(e1.name() + " - " + e1.properties());
System.out.println(e2.name() + " - " + e2.properties());
Run Code Online (Sandbox Code Playgroud)

此代码产生以下输出

ENUM_1_CONST_2 - Properties [value1=2, value2=goodbye, value3=7.54]
ENUM_2_CONST_1 - Properties [value1=9, value2=hey dude, value3=547.21578]
Run Code Online (Sandbox Code Playgroud)

  • @abksrv这就是为什么我问你是否使用java 8。使用java 8,通过默认方法可以很容易地完成你想要的事情。 (2认同)