我对以下示例中的最佳做法提出了这个问题:
interface Request;
interface Service {
void process(Request request)
}
class MyService implements Service;
class YourService implements Service;
class MyRequest implements Request;
class YourRequest implements Request;
但是,如何确保MyService
始终收到MyRequest
和YourService
只会获得YourRequest
,而不是相反的方式? MyService.process(...)
中明显的答案“if-instance-of-check”看起来很丑陋并且不知何故反对SOLID原则。也许有更好的方法?
也许泛型会很好解决? (但是,如何在必须在Java 1.4下运行的代码中使用它们?)
答案 0 :(得分:6)
简而言之,您正在建立一个您不想遵守的界面,因此它并不是一个理想的设计。
我的意思是,如果MyService实现了Service,那么它必须能够接受任何类型的请求。否则,它不遵循定义的合同。
我会质疑为什么你在这个实例中完全拥有Service接口,如果你确实需要它(对于其他方法)是否适合于那里的进程(请求请求)方法,如果子类不会尊重它。
答案 1 :(得分:3)
如果合同的设计是每个服务可以处理任何类型的请求,那么您的MyService实现(仅接受MyRequest(如果传入其他类型的请求则中断)是错误的。
如果合同的设计是Service和Request子类彼此映射,例如,MyService可以(并且应该)仅处理MyRequest,那么您将需要更改Service的接口。否则,问题中写入的当前界面不会执行问题描述的操作。一种解决方法是参数化服务接口:
interface Service<R> {
void process(R request);
}
然后你的具体MyService将是
public class MyService implements Service<MyRequest> {
public void process (MyRequest r) {/*blah*/}
}
你可以在JDK中看到这个实例的一个例子 - Comparator接口正是这样做的,原因完全相同。 http://java.sun.com/javase/6/docs/api/java/util/Comparator.html
我无法理解您的原因,但如果您仍想将MyRequest的层次限制为请求,那么您可以将Service<R>
与Service<R extends Request>
交换
编辑:这显然不会在1.4中运行,所以为了做同样的事情[1],你需要使用访问者模式。它的丑陋,但1.4很难看=)
interface Service {
void process(Request visitor);
}
interface RequestVisitor {
void visitMyRequest(MyService service);
void visitYourRequest(YourService service);
void visitTheOtherRequest(TheOtherService service);
}
interface Request extends RequestVisitor { /* and any extra methods required for request*/ }
public class MyService implements Service {
public process(Request r) {r.visitMyRequest(this);}
public void doSpecialMyProcessing(MyRequest request) { /* your code using MyRequest*/ }
}
public class YourService implements Service {
public process(Request r) {r.visitYourRequest(this);}
public void doSpecialYourProcessing(YourRequest request) { /* your code using YourRequest */ }
}
public class MyRequest implements Request {
void visitMyRequest(MyService service) {
service.doSpecialMyProcessing(this);
}
void visitYourRequest(YourService service) {
throw new UnsupportedOperation("Cannot call visitYourRequest in MyRequest!");
}
void visitTheOtherRequest(TheOtherService service) {
throw new UnsupportedOperation("Cannot call visitTheOtherRequest in MyRequest!");
}
}
public class YourRequest implements Request {
void visitMyRequest(MyService service) {
throw new UnsupportedOperation("Cannot call visitMyRequest in YourRequest !");
}
void visitYourRequest(YourService service) {
service. doSpecialYourProcessing(this);
}
void visitTheOtherRequest(TheOtherService service) {
throw new UnsupportedOperation("Cannot call visitTheOtherRequest in YourRequest !");
}
}
[1] 实际上它不一样,因为现在你需要为每个请求子类型编写一个方法。在1.4中,你必须强制转换和执行instanceof等,以实现1.5对泛型的处理。
答案 2 :(得分:2)
在我看来,仿制药在这里会更合适。您的接口假装服务可以处理任何类型的请求。但实际上每个的实现似乎是紧密耦合的。
答案 3 :(得分:0)
任何实现Service的东西都应该按原样实现它的方法。如果MyService和YourService需要不同的方法原型,那么它们就是不同的接口。
从另一个方向考虑它。在不知道Service接口背后的实现的情况下,任何调用者都应该能够使用Request的任何实现来调用Service.process(request),并期望得到有效的响应。
答案 4 :(得分:0)
尝试引入另一个间接层:
interface Module {
Service createService();
Request createRequest();
}
class MyModule implements Module {
Service createService() { return new MyService(); }
Request createRequest() { return new MyRequest(); }
}
class YourModule implements Module {
Service createService() { return new YourService(); }
Request createRequest() { return new YourRequest(); }
}