Java generic interfaces with typesafe implementations

前端 未结 2 1507
长情又很酷
长情又很酷 2021-01-28 05:27

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 cod

相关标签:
2条回答
  • 2021-01-28 05:49

    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);
    }
    

    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>).

    0 讨论(0)
  • 2021-01-28 05:57

    It seems to me like you're setting yourself up for a messy implementation by having three parallel inheritance hierarchies. May I ask, why can't you merge the Component and ReportBuilder's shared behavior? Effectively, you lose any abstraction on the components by forcing the service caller to know the subclass of the Report they want.

    I'd suggest simplifying the interface by minimizing or eliminating the parameters to buildReport()

     public class ReportService {
        ReportComponentRepository repo;
        List<ReportBuilder> builders;
    
        public <T extends Report> T getReport(Class<T> reportType) {
    
            // Build report from components using one of the registered builders
            for (ReportBuilder builder : builders) {
                if (builder.buildFor(reportType) {
                    //don't pass components - if there's a requirement 
                    //for a strongly typed subclass of Component, just 
                    //let the Report instance figure it out.
                    return builder.buildReport();
                }
            }
        }
    }
    
    
    //example use
    public class PDFReportBuilder implements ReportBuilder {
    
        ComponentSource componentSource;
    
        @Override
        public Report buildReport() {
             PDFReport report;
    
             for (PDFComponent component : componentSource.getPDFComponents()) {
                // assemble report ... 
                report.includeComponent(component);
                // no instanceof operations!
            }
    
            return report;
        }
    }
    
    0 讨论(0)
提交回复
热议问题