In my Spring Boot app, I am trying to implement Template Method and in my concrete class, I am trying to use generic as shown below:
template interface: Not sure if I need to use it?
public interface PDFGenerator {
String createHtml(UUID uuid);
}
template abstract class:
public abstract class AbstractPDFGenerator<T> implements PDFGenerator {
@Override
public String createHtml(UUID uuid) {
T dto = getDTO(uuid);
Context context = new Context();
context.setVariable(getName(), dto.getName());
// ...
}
protected abstract T getDTO(UUID uuid);
protected abstract String getName();
// code omitted
}
concrete classes:
@Service
@RequiredArgsConstructor
public class BrandPDFGenerator extends AbstractPDFGenerator<BrandDTO> {
private static final String NAME = "brandName";
private final BrandService brandService;
@Override
protected String getName() {
return NAME;
}
@Override
protected BrandDTO getDTO(UUID uuid) {
return brandService.findByUuid(uuid);
}
// ...
}
@Service
@RequiredArgsConstructor
public class ProductPDFGenerator extends AbstractPDFGenerator<ProductDTO> {
private static final String NAME = "productName";
private final ProductService productService;
@Override
protected String getName() {
return NAME;
}
@Override
protected ProductDTO getDTO(UUID uuid) {
return productService.findByUuid(uuid);
}
// ...
}
I get "Cannot resolve method 'getName' in 'T'" at the dto.getName() line in AbstractPDFGenerator.
My questions are:
In order to fix the problem, I think of extending T from a base class from which
BrandDTOandProductDTOare inherit. However, I do not want to inherit them from a base class as they have not used similar purpose. So, how can I fix that problem ("Cannot resolve method 'getName' in 'T'")?Do I need to use
PDFGeneratorinterface? Or should I remove it?
Option 1: Use interface, not abstract class. Abstract class will work, but dtos must have correct relationship with each other. If they don't have
is arelationship with the base class, it will be wrong.Then make
BrandDTOandProductDTOimplement it, and introduce a bound forT- only implementations ofHasName.Option 2: Don't use generics. Keep in mind this option won't let you use template method pattern and will lead to code duplication.
Concrete implementations of
setDataInContextwill take care to set correct data, they will work with the actual dto, and generic is not needed.The implementation of
BrandPDFGeneratorwill be the same, except finding the dto.