Sean Nguyen
Sean Nguyen

Reputation: 13128

java template design

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

Answers (2)

padis
padis

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

jzd
jzd

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

Related Questions