当应用于许多类时,以面向对象的方式使用枚举

时间:2015-06-10 21:09:53

标签: java oop enums

所以,我这是我之前的代码:

public enum eDay {
eMON,
eTUE,
eWED
}

eDay day = eMON;

switch( day ) {
case eMON:
//load class 1
break;

case eTUE:
//load class 2
break;

case eWED:
//load class 3
break;
}

阅读,OO的做法是使用枚举来覆盖方法而不是使用switch语句,例如:

enum eDay {
    eMON {
        @Override
        public void loadClass() {
            //load class 1
        }
    },
    eTUE {
        @Override
        public void loadClass() {
            //load class 2
        }
    };
    public abstract void loadClass();
}

void aMethodSomewhere(final eDay e) {
    e.loadClass();
}

虽然使用多态的概念对我有意义,而不是使用switch语句,但是在不同的类中使用枚举来执行不同的事情会发生什么?例如,根据enum中定义的一组有限选项(因此并不总是执行loadClass()),不同的类的行为会有所不同。

您应该根据不同的类定义不同的方法吗?在我看来,这会极大地增加对象耦合。

我真的很想做正确的OO,所以非常感谢好的建议。

非常感谢。

3 个答案:

答案 0 :(得分:1)

Java中的

枚举用于不可更改和定义的常量 在我看来,你希望根据某些条件拥有不同行为的类。如果是这样,策略模式将更适合此任务。

如需更多信息,请点击here

答案 1 :(得分:1)

我建议不要将这种行为放在枚举中;这真的不是他们为 * 设计的。相反,维护枚举和处理程序的地图可能会更好。

Map<Eday, Loader> enumHandlerMap = new EnumMap<>();

Loader应该是一个界面(基本上就是你的枚举中的东西):

public interface Loader {
    void loadClass();
}

然后您可以像这样初始化您的处理程序映射:

enumHanderMap.put(EDay.MON, new Loader() {
    @Override
    public void loadClass() {
        ...
    }
});

你可以像这样运行一个处理程序:

enumHandler.get(eDayEnum).loadClass();

* 为了澄清,枚举传达的语义是您正在处理静态预定义值集。我认为在枚举中包含的可接受的逻辑形式是提供有关每个值的附加信息的类型。 Planet枚举是一个很好的例子,因为它提供了与每个枚举相关的附加信息。没有严格的规则来定义什么是&#34;太多&#34;逻辑。但是如果你发现自己在枚举上实现一个与数据库对话的方法,或者建立一个HTTP连接,我会认为你做得太多了。通常,您在枚举中实现的逻辑不应该与您的模型或业务逻辑的其他部分有关;它不应该需要访问您的模型或其他服务中的其他实体。如果您可以在枚举本身的上下文中传达的其他信息和行为,那么您可能没问题。但是,如果您使用枚举来实现涉及其他实体或服务的复杂行为,那么枚举就会做得太多。

答案 2 :(得分:1)

通常,您希望使用多态来避免if()块,并且对于行为重用,您应该支持组合。

在您的情况下,我了解您的设计中涉及一些动态行为,因此,不建议使用枚举。

枚举有很多优点:它们是最终的,静态的,默认情况下每个实例都是单例。每当我需要一个在JVM启动时启动的静态单例时,我更喜欢枚举而不是类。

在这种情况下,如果您正在进行某些动态行为,则可以编写一个具有一些静态最终属性的类,这些属性是同一个类的实例。使用适用于构造函数或工厂方法的可见性修饰符,类的外部API可以与枚举相同。

为了注入动态行为,您可以使用Strategy design pattern甚至注入一个Function(如果您使用的是Java8)作为类'构造函数中的参数。

public static class eDays {
  public static final eDay eMON = new eDay(i -> i + 1);
  public static final eDay eTUE = new eDay(i -> i + 2);

  public static class eDay {
    private final Function<Integer, Integer> loadClassStrategy;

    public eDay(Function<Integer, Integer> loadClassStrategy) {
      this.loadClassStrategy = loadClassStrategy;
    }

    public int loadClass(int i) {
      return loadClassStrategy.apply(i);
    }
  }
}

void aMethodSomewhere(final eDays.eDay e) {
  e.loadClass(1);
}

// or even...

void aMethodSomewhere() {
  eDay eMON = new eDay(i -> i + 1);
  eMON.loadClass(1);
}

如果您的行为不是动态的,您可以继续使用枚举,但您可以在其构造函数中注入该行为以提高可读性:

public enum eDay {
  eMON(i->i+1),
  eTUE(i->i+2);

  private final Function<Integer, Integer> loadClassStrategy;

  eDay(Function<Integer, Integer> loadClassStrategy) {
    this.loadClassStrategy = loadClassStrategy;
  }

  public int loadClass(int i) {
    return loadClassStrategy.apply(i);
  }
}

void aMethodSomewhere(eDay e) {
  e.loadClass(1);
}