假設某需求,有個計算器實現了加、減、乘、除的算法,但是希望同時也允許客戶端自定義某些操作方法。
計算器實現的加、減、乘、除代碼如下:
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;
}
}
此時,已經滿足了需求的設計。有個缺點就是BasicOperation
和ExtendOperation
之間重複的代碼比較多。如果是重複代碼非常大的話,建議將重複代碼移到工具類中。