Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design Pattern for Data Structure with Methods to Populate It?

I have a data structure in Java that I am populating via different methods. One method populates it from an API, another method populates it from parsing some HTML, another populates it a different way, etc. Basically, a method for every data source that could populate it. What I'm wondering is, what design patterns are available in Java for this? What's the best/cleanest OOP approach to this problem?

E.g.,

public class Data {
    private String foo;
    private List<String> bar;
    private Map<String, Integer> baz;

    public Data (String foo, List<String> bar, Map<String, Integer baz) {
        this.foo = foo;
        this.bar = bar;
        this.baz = baz;
    }

    // Setters and Getters here, etc
}


public class FacebookParser {
    private Document dom;

    public static Data parse(Document dom) {
        // Parse document
        // Create Data object
        return Data;
    }
}

public class TwitterParser {
    private Document dom;

    public static Data parse(Document dom) {
       // Parse Twitter
       Data d = new Data(stuff from twitter);
       return d;
    }
}
like image 783
Frankie's Deadhead Avatar asked Feb 23 '16 23:02

Frankie's Deadhead


2 Answers

You want a Data and it is represented in different forms. The part that you are interested in should be defined in an abstract way. So making the Data an interface is a good point for starting.

public interface Data {
    String getFoo();
    List<String> getBar();
    Map<String, Integer> getBaz();
}

This data is obtained from different providers. The common thing is we need someone to provide Data. In the end, the only thing we are interested in is the Data itself, not how it is parsed or provided. So we need a simple DataProvider interface.

public interface DataProvider {
    Data createData();
}

Now we can implement the provider classes those know how to fetch, parse, process etc. the data. Provider classes should not be dealing with how to convert the provider specific data into our common Data interface. They are only responsible for creating a Data implementation that they know.

public class FacebookDataProvider implements DataProvider {
    public Data createData() {
        FacebookSpecificInfo x = ...

        FacebookData data = new FacebookData();

        // Note that this class does not know anything about foo, bar and baz.
        // We are still Facebook context.
        data.setName(x.getName());
        data.setValues(x.getValues());
        data.setHeaders(x.getHeaders());

        return data;
    }
}

class FacebookData implements Data {
    private String name;
    private List<String> values;
    private Map<String, Integer> headers;

    void setName(String name) { this.name = name; }
    void setValues(String values) { this.values = values; }
    void setHeaders(String headers) { this.headers = headers; }

    // This is the part where we switch the context and convert
    // Facebook specific data into our expected Data
    // ie. Facebook's name field corresponds my foo field.

    public String getFoo() { return name; }
    public List<String> getBar() { return values; }
    public Map<String, Integer> getBaz() { return headers; }
}
like image 192
Mehmet Ataş Avatar answered Oct 12 '22 22:10

Mehmet Ataş


What you can do is have a separate class for setting the values of the Data class.

You can have something like this :

public class DataPopulator{

  public void setTwitterData(Data d){
     //your data
  } 

  public void setFacebookData(Data d){
     //your data
  } 

}

This is something similar to Adapter Design pattern, though not exactly same.

You can have a look at it here.

like image 38
Pritam Banerjee Avatar answered Oct 12 '22 22:10

Pritam Banerjee