如何在添加新的枚举值时避免更改许多代码部分,从而提供更容易的扩展性?

How to avoid changing many parts of code when adding new enum value, thus providing easier extensibility?

我正在努力使我的代码更易于扩展,因为一点点更改不会影响其他代码。

我有一个 enum MyEnum,它的值将来可能会增加。

然后,有 类 保存它的实例,并且有许多行为受 enum 的具体值影响。换句话说,有很多地方我切换了它的值。

public enum MyEnum
{
    FIRST, SECOND, THIRD, FOURTH;
}


public class A
{
    private MyEnum myEnum
    
    public A(MyEnum myEnum)
    {
        this.myEnum = myEnum;
    }
    
    // as you will see, there is a lot of switching over its value
    public void boo()
    {
        switch(myEnum)
        {
            case FIRST: // do smtng
            case SECOND: // do smthing else
            case THIRD: // do smthing else
            case FOURTH: // do nice thing
        }
    }

    public int goo()
    {
        switch(myEnum)
        {
            ...
        }
    }
   

    public AnotherObject foo()
    {
        switch(myEnum)
        {
            ...
        }
    }
}

public class B
{
    private MyEnum myEnum
    
    public B(MyEnum myEnum)
    {
        this.myEnum = myEnum;
    }
    
    public double doo()
    {
        switch(myEnum)
        {
            ...
        }
    }

    public void soo()
    {
        switch(myEnum)
        {
            ...
        }
    }
   
    public boolean xoo()
    {
        switch(myEnum)
        {
            ...
        }
    }
}

这里的事情是主要我需要在我们切换它的值的所有地方添加新的案例=>在我添加时需要对代码做很多更改新 枚举 值。

还有其他人遇到过这个问题吗?到目前为止,我想这只是以这种方式使用 enums 的缺点。

不要将您的代码绑定到 enum 将您的代码绑定到接口。然后让您的枚举提供接口的标准实现。

public interface RibbonColor {
   public String getColor();
}

public enum DefaultRibbonColors implements RibbonColor {
   FIRST() {
      public String getColor() {
        return "blue";
      }
   }, 
   SECOND() {
      public String getColor() {
        return "red";
      }
   },
   THIRD() {
      public String getColor() {
        return "white";
      }
   },
}

public class Awards {

   private List<RibbonColor> ribbons;

   public Awards(List<RibbonColor> ribbons) {
      this.ribbons = ribbons;
   }

   public RibbonColor awardFor(int placeIndex) {
      if (placeIndex < ribbons.length()) {
        return ribbons.get(placeIndex).getColor();
      }
      return null;
   }

}

请注意,现在您可以通过

轻松添加所有默认 Awards 的新列表
Awards awards = new Awards(Arrays.asList(DefaultRibbonColors.values()));

同时您还可以创建自定义奖励集。

List ribbons = new ArrayList<RibbonColor>();
ribbons.addAll(DefaultRibbonColors.values());
ribbons.addAll(ExtendedRibbonColors.values());
ribbons.addAll(new BlackAndPinkPolkaDotRibbonColor());

Awards awards = new Awards(ribbons);

关键是永远不要让代码真正依赖于 enum,因为如果不重新编译就无法修改 enum,这会触发搜索 switch 的需要缺少 default: 块或附加值的更明确设置的语句。

对象是“代码和数据一起编写”,而过程代码是“代码和数据分开管理” switch 语句将逻辑“代码”放在“数据”类型之外,这是一个编程错误在 100% 疯狂的面向对象设计中。也就是说,它通常很有用,人们仍然使用 Java 和其他语言以有效地将代码与数据(保存所有数据的对象,以及操纵另一个对象的数据的“对象例程”)分离的方式构建程序。这对象数据与其例程的一种分离是一种称为 anemic objects.

的反模式

EnumsObjects 所以不要害怕在其中添加方法!在它们应该可复制的地方给它们接口,并避免 switch 语句,因为这可能是一个好兆头,表明逻辑应该在你正在打开的东西中(前提是它是一个对象)。