【Effective Java】條34:使用接口模擬擴展枚舉

假設某需求,有個計算器實現了加、減、乘、除的算法,但是希望同時也允許客戶端自定義某些操作方法。

計算器實現的加、減、乘、除代碼如下:

public enum Operation {
  PLUS("+") {
    @Override
    double apply(double x, double y) {
      return x + y;
    }
  },

  MINUS("-") {
    @Override
    double apply(double x, double y) {
      return x - y;
    }
  },

  TIMES("*") {
    @Override
    double apply(double x, double y) {
      return x * y;
    }
  },

  DIVIDE("/") {
    @Override
    double apply(double x, double y) {
      return x / y;
    }
  };

  private String symbol;
  public static final Map<String, Operation> OPERS_MAP = Maps.newHashMap();

  static {
    for (Operation op : Operation.values()) {
      OPERS_MAP.put(op.toString(), op);
    }
  }

  Operation(String symbol) {
    this.symbol = symbol;
  }

  @Override
  public String toString() {
    return symbol;
  }

  abstract double apply(double x, double y);
}

由於enum不支持繼承,又由於Operation有可能你並不能修改代碼,而是第三方提供的類庫。該如何實現?此時,我們可以將enum實例域的方法提取成爲接口,而enum是可以實現接口的,用戶自定義的操作方法也只需實現該接口,只是確保在調用計算器方法的參數時使用的是接口類型即可。如:

public interface Operation {
    double apply(double x, double y);
}

public enum BasicOperation implements Operation {
    PLUS("+") {
        @Override
        double apply(double x, double y) {
          return x + y;
        }
    },

    MINUS("-") {
        @Override
        double apply(double x, double y) {
          return x - y;
        }
    },

    TIMES("*") {
        @Override
        double apply(double x, double y) {
          return x * y;
        }
    },

    DIVIDE("/") {
        @Override
        double apply(double x, double y) {
          return x / y;
        }
    };

    private String symbol;
    public static final Map<String, Operation> OPERS_MAP = Maps.newHashMap();

    static {
        for (Operation op : BasicOperation.values()) {
          OPERS_MAP.put(op.toString(), op);
        }
    }

    Operation(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }
}

//客戶端自定義操作
public enum ExtendOperation implements Operation {
    EXP("^") {
        @Override
        public double apply(double x, double y) {
            return Math.pow(x, y);
        }
    },
    REMAINDER("%") {
        @Override
        public double apply(double x, double y) {
            return x % y;
        }
    };

    private String symbol;
    public static final Map<String, Operation> OPERS_MAP = Maps.newHashMap();

    static {
        for (Operation op : ExtendOperation.values()) {
          OPERS_MAP.put(op.toString(), op);
        }
    }

    Operation(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }
}

此時,已經滿足了需求的設計。有個缺點就是BasicOperationExtendOperation之間重複的代碼比較多。如果是重複代碼非常大的話,建議將重複代碼移到工具類中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章