Reputation: 13128
public class Converter
{
private Logger logger = Logger.getLogger(Converter.class);
public String convert(String s){
if (s == null) throw new IllegalArgumentException("input can't be null");
logger.debug("Input = " + s);
String r = s + "abc";
logger.debug("Output = " + s);
return r;
}
public Integer convert(Integer s){
if (s == null) throw new IllegalArgumentException("input can't be null");
logger.debug("Input = " + s);
Integer r = s + 10;
logger.debug("Output = " + s);
return r;
}
}
The above 2 methods are very similar so I want to create a template to do the similar things and delegate the actual work to the approriate class. But I also want to easily extends this frame work without changing the template. So for example:
public class ConverterTemplate
{
private Logger logger = Logger.getLogger(Converter.class);
public Object convert(Object s){
if (s == null) throw new IllegalArgumentException("input can't be null");
logger.debug("Input = " + s);
Object r = doConverter();
logger.debug("Output = " + s);
return r;
}
protected abstract Object doConverter(Object arg);
}
public class MyConverter extends ConverterTemplate
{
protected String doConverter(String str)
{
String r = str + "abc";
return r;
}
protected Integer doConverter(Integer arg)
{
Integer r = arg + 10;
return r;
}
}
But that doesn't work. Can anybody suggest me a better way to do that? I want to achieve 2 goals: 1. A template that is extensible and does all the similar work for me. 2. I ant to minimize the number of extended class.
Thanks,
Upvotes: 3
Views: 269
Reputation: 2354
Use generics, make convert method final (so it is not overridden when you want to keep this template) and make converter implementation for each type in separate class:
public interface Converter<T> {
public T convert(T s);
}
public abstract class AbstractConverter<T> implements Converter<T> {
@Override
public final T convert(T s) {
if (s == null) throw new IllegalArgumentException("input can't be null");
//logger.debug("Input = " + s);
T r = doConverter(s);
//logger.debug("Output = " + s);
return r;
}
public abstract T doConverter(T s);
}
public class StringConverter extends AbstractConverter<String> {
public String doConverter(String s) {
String r = s + "abc";
return r;
};
}
public class IntegerConverter extends AbstractConverter<Integer> {
public Integer doConverter(Integer s) {
Integer r = s + 10;
return r;
};
}
Upvotes: 5
Reputation: 23629
This is a perfect case to use generics. More specifically you can specify that the parent class have a "generic" class that it takes and uses for doConvert. Then the extensions would each specify the type of class that they are using.
Upvotes: 1