【问题标题】:Java Wrapper enum switch polymorphismJava Wrapper 枚举开关多态性
【发布时间】:2015-03-18 01:22:44
【问题描述】:

我在原始界面中使用 Wrapper 获得了这段代码。基于枚举,a 会调用链表的方法,如 putFirst(T data)、putCurrent(T data)、putLast()、removeFirst()、...

...

@Override
public void put(T data, EnumPosition position) {

    switch (position) {
        case FIRST:
            abstrList.putFirst();
            break;

        case LAST:
            abstrList.putLast();
            break;

        ...

        default:
           throw new NoSuchElementException("something exception...");
    }

@Override
public void remove(T data, EnumPosition position) {

    switch (position) {
        case FIRST:
            abstrList.removeFirst(data);
            break;

        case LAST:
            abstrList.removeLast(data);
            break;

        ...

        default:
           throw new NoSuchElementException("something exception...");
    }

我的 EnumPosition 现在看起来很简单。 (可能改变它实现一些接口)

public enum EnumPosition {
     FIRST, LAST, CURRENT ...

}

A 想问一下,是否可以移除这个开关并用一些多态性替换它,使用 java 8 中的 lambda 或其他......更有效的东西。

感谢您的帮助

【问题讨论】:

    标签: java design-patterns enums polymorphism wrapper


    【解决方案1】:

    枚举状态机呢?我不确定它是否能解决您的问题,但您可以尝试像这样编辑您的界面:

        public enum EnumPosition {
        FIRST {
          @Override
          public void doPut(){
             abstrList.putFirst();
          }
          @Override
          public void doGet(){
             abstrList.getFirst();
          }
        },
        LAST {
          ... // Override methods for LAST
        },
        CURRENT {
          ...
        },
    
        ...
    
        public abstract void doPut();
        public abstract void doGet();
        }
    

    这些更改后,您可以避免使用此切换:

    ...
    
    @Override
    public void put(T data, EnumPosition position) {
           position.doPut();
        }
    

    您可以在这里找到更多信息:https://schneide.wordpress.com/2010/12/13/avoid-switch-use-enum/

    【讨论】:

      【解决方案2】:

      是的。但是,答案取决于您如何使用枚举。

      您总是一遍又一遍地传递相同的枚举值还是混淆了?

      如果你总是使用相同的枚举

      您可以制作多个采用List 的包装器实现,并制作一个采用枚举来确定实现的工厂(或使其成为枚举本身的工厂方法)。

      MyList<T> list = EnumPosition.LAST.newMyListWrapper(abstrList);
      
      list.put(data);
      list.remove(data);
      

      如果您在通话中混淆了枚举

      如果您同时使用不同的枚举来作用于同一个abstrList,那么您必须将put(List&lt;T&gt; list, T data)remove(List&lt;T&gt; list, data) 方法添加到您的枚举中:

      EnumPosition.LAST.put(abstrList, data);
      
      EnumPosition.CURRENT.remove(abstrList, data);
      

      或者,如果您需要同时支持这两个用例,您可以两者都做...

      【讨论】:

      • 太棒了。谢谢你的回答。
      【解决方案3】:

      由于不能扩展枚举,因此不能直接对枚举使用多态性。

      但是您可以在某种类型的枚举中定义一个实例变量。然后您可以使用多态性,例如

      public enum EnumPosition {
      
          FIRST(new FirstElementModification()), 
          LAST(new LastElementModification())
          ...;
      
          private ListModification listModification;
      
          private EnumPosition(ListModification listModification) {
              this.listModification = listModification;
          }
      
          public <T> void put(List<T> list, T element) {
              listModification.put(list, element);
          }
      
          public void remove(List<?> list) {
              listModification.remove(list);
          }
      
      }
      
      interface ListModification {
          public <T> void put(List<T> list, T element);
          public <T> void remove(List<T> list);
      }
      

      并像这样实现不同的列表修改策略

      class FirstElementModification implements ListModification {
      
          public <T> void put(List<T> list, T element) {
              ...
          }
      
          public <T> void remove(List<T> list) {
              ...
          }
      
      }
      

      从客户端的角度来看,您可以省略开关并直接使用

      EnumPosition.FIRST.put(someList, someElement);
      EnumPosition.LAST.remove(someList);
      

      【讨论】:

      • 很好的解决方案。谢谢你的回答。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 2011-12-23
      • 1970-01-01
      相关资源
      最近更新 更多