有像vert.x这样的防御性编码库。使用带有静态工厂方式的接口来返回实现。开发人员可以使用他们的实现,但是当它不是完全所需的时候 - 它是不可能扩展它的。不幸的是,它甚至将实现绑定到接口。为什么?
扩展此类的推荐方法是什么?除了复制整个班级以外,还必须有其他方法,只需重写几行所需的行......
例如:io.vertx.ext.web.handler.CorsHandler的vert.x实现
public interface CorsHandler {
static CorsHandler create(String allowedOriginPattern) {
return new CorsHandlerImpl(allowedOriginPattern);
}
...
}
public class CorsHandlerImpl implements CorsHandler {
private boolean isValidOrigin(String origin) {
}
...
}
public class MyCorsHandler implement/extends CorsHandler/impl {
@Override
protected boolean isValidOrigin(String origin) {
// my changes
}
}
答案 0 :(得分:1)
可以包装类而不是扩展它,只更改需要不同实现的方法。
此解决方案称为Adapter Pattern:
在软件工程中,适配器模式是一种软件设计模式(也称为Wrapper,与Decorator模式共享的替代命名),它允许将现有类的接口用作另一个接口。1 它经常用于使现有的类与其他类一起使用而无需修改其源代码。
考虑扩展其他人编写的现有类通常不是一个好主意。事实上,在下面的版本中,它们的内部实现可以改变,并且这些更改可以反映在扩展类上,以某种方式无法预测的方式改变它们的行为。
这是一个显示:
的例子想象一下,您需要使用自定义实现扩展ArrayList以记录所有添加的项目。
实际上你可以重写add和addAll方法,如下所示:
public void add(E e) {
System.out.println("add item " + e);
super.add(e);
}
public void addAll(Collection<? extends E> c) {
for (E e : c) {
System.out.println("add item " + e);
}
super.addAll(c);
}
这是有效的,因为addAll
的内部实施不会调用add
。但是,如果addAll
的实现因集合c
上的循环而更改,则会为您的代码无效的每个元素调用add
。因此,更改基类将改变派生类的行为。
答案 1 :(得分:0)
对于CorsHandler,我会继续扩展Impl并覆盖处理方法:
class MyCorsHandler extends CorsHandlerImpl {
public MyCorsHandler(String allowedOriginPattern) {
super(allowedOriginPattern);
}
@Override
public void handle(RoutingContext context) {
HttpServerRequest request = context.request();
HttpServerResponse response = context.response();
String origin = context.request().headers().get(ORIGIN);
if (origin == null) {
// Not a CORS request - we don't set any headers and just call the next handler
context.next();
} else if (isMyValidOrigin(origin)) {
context.next();
} else {
super.handle(context);
}
}
private boolean isMyValidOrigin(String origin) {
// Do something there
return false;
}
}