问题描述
我正在寻找从通用框架调用特定接口的好选择。我将以代码为例。查看问题部分,示例代码主要包括在内,以便将实例置于真实场景中。
I'm look for good alternatives to invoking a specific interface from a generic framework. I'll exemplify with code. Look to the question part, the example code is primarily included for thoroughness, and for putting the example into a real scenario.
假设我们要根据组件列表构建一个报表。假设我们有两个特定的组件类型:
Assume we want to build a report based on a list of components. Say we have two specific component types:
public interface Component { ... }
public class PDFComponents extends Component { ... }
public class WordComponents extends Component { ... }
每个组件都一个ReportBuilder实现,例如,
Each component has a ReportBuilder implementation, e.g.,
public interface ReportBuilder { ... }
public class PDFReportBuilder extends ReportBuilder { ... }
public class WordReportBuilder extends ReportBuilder { ... }
哪些构建特定的报告实现
Which builds specific report implementations
public interface Report { ... }
public class PDFReport extends ReportBuilder { ... }
public class WordReport extends ReportBuilder { ... }
最后我们有了定位组件的服务,报告出组件。
Finally we have the service which locates components and produces a report out of the components.
public class ReportService {
ReportComponentRepository repo;
List<ReportBuilder> builders;
public <T extends Report> T getReport(Class<T> reportType) {
// Get report components. E.g., this might return List<PDFComponent>
List<Component> reportComponents = repo.getReportComponents(id);
// Build report from components using one of the registered builders
for (ReportBuilder builder : builders) {
if (builder.buildFor(reportType) {
return builder.buildReport(report);
}
}
}
}
使用服务的示例
List<PDFReport> reports = new ReportService().getReport(PDFReport.class);
问题
问题。我如何设计一个通用的ReportBuilder界面,允许类似的安全性实现?
Question
Now to the question. How can I design a generic ReportBuilder interface which allows typesafety to it's implementations?
例如,选择界面:
public Report buildReport(List<? extends Component> components);
将导致其执行中的丑陋:
would cause ugliness in it's implementations:
public class PDFReportBuilder implements ReportBuilder {
@Override
public Report buildReport(List<? extends Component> components) {
PDFReport report;
for (Component component : components) {
if (component instanceOf PDFComponent) {
// assemble report ...
report.includeComponent(component);
}
}
return report;
}
}
当我们真正希望PDFReportBuilder的界面为例,
when we really desire the interface for PDFReportBuilder to be e.g.,
public Report buildReport(List<PDFComponent> component) { ... }
推荐答案
如果您将Component的类型设置为ReportBuilder的类型变量,则可以工作:
It works if you make the type of Component into a type variable for ReportBuilder:
public interface ReportBuilder<T extends Component> {
public Report buildReport(List<T> components);
}
public class PDFReportBuilder implements ReportBuilder<PDFComponent> {
public Report buildReport(List<PDFComponent> components);
}
您必须评估您是否真的希望在ReportBuilder中使用类型变量。这并不总是正确的选择。另外,如果您还要 PDFReportBuilder.buildReport
具有PDFReport的返回类型,那么您需要将其作为类型变量(即 public interface ReportBuilder< T extends Component,S extends Report>
)。
You'll have to evaluate whether you really want a type variable in ReportBuilder though. It's not always the correct choice. Additionally, if you also want PDFReportBuilder.buildReport
to have a return type that is PDFReport, then you need to have that as a type variable as well (i.e., public interface ReportBuilder<T extends Component, S extends Report>
).
这篇关于具有类型安全实现的Java通用接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!