假设某需求,有个计算器实现了加、减、乘、除的算法,但是希望同时也允许客户端自定义某些操作方法。
计算器实现的加、减、乘、除代码如下:
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
之间重复的代码比较多。如果是重复代码非常大的话,建议将重复代码移到工具类中。