genericsdesign-patternstemplate-method-pattern

Design pattern for different input parameter type and data extraction algorithm


I am new to design pattern.

My question is what pattern do I use in below case?

interface UserExtractorService {
    String getUser(XXXX);
    default validate(File file);
}

class AExtractorService {
    public String getUser(String url) {
           validate(downloadfromWeb(url));
       return getFromWeb(url);
    }
}

class BExtractorService {
    public String getUser(File) {
           validate(file);
           parsingFromFile(File);
       return parsingFromFile(File);
    }
}

class Client {

    public void GetUsers(String key) {
         userExtractorService.getUser(key);
    }

    public void GetUsers(File file) {
         userExtractorService.getUser(file);
    }
}

I want to group AExtractor and BExtractor, because it need operate similar behavior.


Solution

  • If one takes a closer look at the user-case, it should be clear that there are two main aspects of the design that need to be flexible :

    1. The parameter type of the getUser method can be String in one case and File in other cases.
    2. The mechanism to extract the user data will vary depending on the source i.e, extract from a web url or a file

    Point 1 can be tackled by using generics/template functions where UserExtractorService can have a type parameter or the getUser method can have a type parameter. The type parameter of the class or function would represent the input parameter type for the getUser function and would be defined by the client while instantiating the UserExtractorService implementations.

    Point 2 can be tackled by using the Template method design pattern. Note that this is different from C++ template classes and methods. Template method pattern is a behavioral design pattern that defines the program skeleton of an algorithm in an operation, defering some steps to subclasses.

    Translating this to code, the getUser method would be the template method. Next, one would define an abstract method called String extractUserData(T source) which would be called in getUser. This abstract method will be implemented by subclasses and would contain the algorithm for extracting data from a particular source. We would essentially have one subclass per source of user data (Web, File) etc. An example of the getUser method in Java would be as follows :

    abstract class UserExtractorService<T> {
       public final String getUser(T source) {
             validate(source);
             return extractUserData(source);
       }
    
       protected abstract String extractUserData(T source);
       protected abstract void validate(File f);
    }